blob: 4ccf516b88ee25836df57ba54903667309ff04f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 xored software, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* xored software, Inc. - initial API and Implementation (Andrei Sobolev)
*******************************************************************************/
package org.eclipse.dltk.internal.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IModelProvider;
import org.eclipse.dltk.core.IProjectFragmentFactory;
import org.eclipse.dltk.core.SimpleClassDLTKExtensionManager;
import org.eclipse.dltk.core.SimpleDLTKExtensionManager.ElementInfo;
import org.eclipse.dltk.utils.NatureExtensionManager;
/**
* Used to provide or replace some model elements in structure model.
*/
public class ModelProviderManager {
private static final String EXT_POINT = DLTKCore.PLUGIN_ID + ".model";
private static final String REQUIRES = "requires";
private static final String ID = "id";
private static final String LANGUAGE = "language";
private static Map<String, IModelProvider[]> providers = null;
public synchronized static IModelProvider[] getProviders(String lang) {
if (providers == null) {
providers = new HashMap<>();
final SimpleClassDLTKExtensionManager manager = new SimpleClassDLTKExtensionManager(
EXT_POINT) {
@Override
protected boolean isValidElement(
IConfigurationElement confElement) {
return "model".equals(confElement.getName());
}
};
ElementInfo[] infos = manager.getElementInfos();
Map<String, List<ElementInfo>> langToElementList = new HashMap<>();
// Fill element names and sort elements by language
for (int i = 0; i < infos.length; i++) {
String langauge = infos[i].getConfig().getAttribute(LANGUAGE);
if (langToElementList.containsKey(langauge)) {
List<ElementInfo> elements = langToElementList
.get(langauge);
elements.add(infos[i]);
} else {
List<ElementInfo> elements = new ArrayList<>();
elements.add(infos[i]);
langToElementList.put(langauge, elements);
}
}
for (Map.Entry<String, List<ElementInfo>> entry : langToElementList
.entrySet()) {
String language = entry.getKey();
List<ElementInfo> elements = entry.getValue();
Map<String, ElementInfo> names = new HashMap<>(); // Contains
// map
// for
// all
// ids
for (int i = 0; i < elements.size(); i++) {
ElementInfo info = elements.get(i);
String name = info.getConfig().getAttribute(ID);
names.put(name, info);
}
List<IModelProvider> result = new ArrayList<>(); // Final
// IModelProvider
// elements
Set<String> added = new HashSet<>(); // Contain names for
// added elements
// Process elements and keep dependencies
List<ElementInfo> toProcess = new ArrayList<>();
toProcess.addAll(elements);
while (!toProcess.isEmpty()) {
ElementInfo info = toProcess.remove(0);
String requires = info.getConfig().getAttribute(REQUIRES);
if (requires == null) {
result.add(
(IModelProvider) manager.getInitObject(info));
} else {
String req = requires.trim();
if (added.contains(req)) { // Dependency
// present
result.add((IModelProvider) info.object);
} else {
if (names.containsKey(req)) { // Dependency exist
// Add element to end of process
toProcess.add(info);
added.add(info.getConfig().getAttribute(ID));
} else {
// Dependency doesn't exists so add to results
result.add((IModelProvider) info.object);
added.add(info.getConfig().getAttribute(ID));
}
}
}
}
providers.put(language,
result.toArray(new IModelProvider[result.size()]));
}
}
return providers.get(lang);
}
private static final NatureExtensionManager<IProjectFragmentFactory> projectFragmentFactories = new NatureExtensionManager<IProjectFragmentFactory>(
EXT_POINT, IProjectFragmentFactory.class) {
@Override
protected boolean isValidElement(IConfigurationElement element) {
return "projectFragment".equals(element.getName());
}
};
public static IProjectFragmentFactory[] getProjectFragmentFactories(
String natureId) {
return projectFragmentFactories.getInstances(natureId);
}
}