/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* All rights reserved. This program and the accompanying materials are made available under
* the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package gov.redhawk.ide.codegen.internal;
import gov.redhawk.ide.codegen.ICodeGeneratorDescriptor;
import gov.redhawk.ide.codegen.ICodeGeneratorsRegistry;
import gov.redhawk.ide.codegen.RedhawkCodegenActivator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IFilter;
/**
* @since 2.0
*/
public class CodeGeneratorsRegistry implements ICodeGeneratorsRegistry, IExtensionChangeHandler {
public static final String EP_ID = "codegens";
/**
* The Constant ATTR_CODEGEN
*/
private static final String ATTR_CODEGEN = "codegen";
private static final StringComparator STRING_COMPARATOR = new CodeGeneratorsRegistry.StringComparator();
/**
* Create a tracker.
*/
private final ExtensionTracker tracker;
/**
* The codegen Codegen objects.
*/
private final Map<String, ICodeGeneratorDescriptor> codegenMap = new HashMap<String, ICodeGeneratorDescriptor>();;
/**
* The codegen Codegen objects.
*/
private final Map<String, Set<String>> langToIdMap = new HashMap<String, Set<String>>();
public CodeGeneratorsRegistry() {
final IExtensionRegistry reg = Platform.getExtensionRegistry();
final IExtensionPoint ep = reg.getExtensionPoint(RedhawkCodegenActivator.PLUGIN_ID, CodeGeneratorsRegistry.EP_ID);
this.tracker = new ExtensionTracker(reg);
if (ep != null) {
final IFilter filter = ExtensionTracker.createExtensionPointFilter(ep);
this.tracker.registerHandler(this, filter);
final IExtension[] extensions = ep.getExtensions();
for (final IExtension extension : extensions) {
addExtension(this.tracker, extension);
}
}
}
@Override
public void addExtension(final IExtensionTracker tracker, final IExtension extension) {
final IConfigurationElement[] configs = extension.getConfigurationElements();
for (final IConfigurationElement element : configs) {
final ICodeGeneratorDescriptor desc = addConfig(element);
if (desc != null) {
tracker.registerObject(extension, desc, IExtensionTracker.REF_SOFT);
}
}
}
private ICodeGeneratorDescriptor addConfig(final IConfigurationElement element) {
if (element.getName().equals(CodeGeneratorsRegistry.ATTR_CODEGEN)) {
final CodeGeneratorDescriptor desc = new CodeGeneratorDescriptor(element);
if (!this.codegenMap.containsKey(desc.getId())) {
this.codegenMap.put(desc.getId(), desc);
final String lang = desc.getLanguage();
Set<String> ids = this.langToIdMap.get(lang);
if (ids == null) {
ids = new HashSet<String>();
this.langToIdMap.put(lang, ids);
}
ids.add(desc.getId());
return desc;
} else {
RedhawkCodegenActivator.logError("Duplicate Code Generator registered with an ID of: " + desc.getId(), null);
}
}
return null;
}
@Override
public void removeExtension(final IExtension extension, final Object[] objects) {
for (final Object obj : objects) {
if (obj instanceof ICodeGeneratorDescriptor) {
final ICodeGeneratorDescriptor desc = (ICodeGeneratorDescriptor) obj;
this.codegenMap.remove(desc.getId());
final Set<String> ids = this.langToIdMap.get(desc.getLanguage());
ids.remove(desc.getId());
if (ids.size() == 0) {
this.langToIdMap.remove(desc.getLanguage());
}
}
}
}
@Override
public ICodeGeneratorDescriptor findCodegen(final String id) {
return this.codegenMap.get(id);
}
@Override
public ICodeGeneratorDescriptor[] getCodegens() {
return this.codegenMap.values().toArray(new ICodeGeneratorDescriptor[this.codegenMap.size()]);
}
@Override
public String[] getLanguages() {
Set<String> languages = new HashSet<String>(this.langToIdMap.keySet());
languages.remove("*");
final String[] keys = languages.toArray(new String[languages.size()]);
Arrays.sort(keys, CodeGeneratorsRegistry.STRING_COMPARATOR);
return keys;
}
@Override
public ICodeGeneratorDescriptor[] findCodegenByLanguage(final String language) {
return findCodegenByLanguage(language, null);
}
/**
* @since 9.0
*/
@Override
public ICodeGeneratorDescriptor[] findCodegenByLanguage(final String language, final String componentType) {
final Set<String> ids = this.langToIdMap.get(language);
if (ids == null) {
return new ICodeGeneratorDescriptor[0];
}
final Set<String> wildcard = this.langToIdMap.get("*");
if (wildcard != null) {
ids.addAll(wildcard);
}
final ArrayList<ICodeGeneratorDescriptor> codegens = new ArrayList<ICodeGeneratorDescriptor>();
for (final String id : ids) {
final ICodeGeneratorDescriptor codegen = this.codegenMap.get(id);
if (codegen != null) {
if ((componentType == null) || (codegen.supportsComponentType(componentType))) {
codegens.add(codegen);
}
}
}
Collections.sort(codegens, new PriorityComparator());
return codegens.toArray(new ICodeGeneratorDescriptor[codegens.size()]);
}
private static class StringComparator implements Comparator<String> {
@Override
public int compare(final String o1, final String o2) {
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
return o1.compareTo(o2);
}
}
private static class PriorityComparator implements Comparator<ICodeGeneratorDescriptor> {
private static HashMap<String, Integer> priorityMap = new HashMap<String, Integer>();
{
priorityMap.put("high", 0);
priorityMap.put("normal", 1);
priorityMap.put("low", 2);
}
@Override
public int compare(final ICodeGeneratorDescriptor o1, final ICodeGeneratorDescriptor o2) {
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
Integer p1 = priorityMap.get(o1.getPriority());
Integer p2 = priorityMap.get(o2.getPriority());
if (p1 == null) {
return 1;
}
if (p2 == null) {
return -1;
}
return p1.compareTo(p2);
}
}
}