blob: d67b5375b881c87f01a5870b94f8343b000c7ee8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Oracle Corporation.
* 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
*
* Contributors:
* Gerry Kessler/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.metadataprocessors.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.metadataprocessors.IType;
/**
* Registry of <code>AbstractMetaDataEnabledType</code>s loaded from
* the <code>MetaDataEnabledFeatures</code> extension point
*
* A map of features keyed by type id
*
*/
public class MetaDataEnabledFeatureRegistry{
private static final String EXTPTID = "MetaDataEnabledFeatures"; //$NON-NLS-1$
private Map<String, List<IMetaDataEnabledFeatureExtension>> featuresMap;
private Map<String, Class> typeCacheMap;
private static MetaDataEnabledFeatureRegistry INSTANCE;
/**
* @return the singleton instance of the MetaDataEnabledFeatureRegistry
*/
public static synchronized MetaDataEnabledFeatureRegistry getInstance(){
if (INSTANCE == null){
INSTANCE = new MetaDataEnabledFeatureRegistry();
}
return INSTANCE;
}
private MetaDataEnabledFeatureRegistry(){
featuresMap = new HashMap<String, List<IMetaDataEnabledFeatureExtension>>();
typeCacheMap = new HashMap<String, Class>();
readRegistry();
}
/**
* Reads the MetaDataEnabledFeatures extensions into a registry
*/
protected void readRegistry() {
try {
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(JSFCorePlugin.PLUGIN_ID, EXTPTID);
IExtension[] extensions = point.getExtensions();
for (int i=0;i < extensions.length;i++){
IExtension ext = extensions[i];
for (int j=0;j < ext.getConfigurationElements().length;j++){
final String bundleId = ext.getConfigurationElements()[j].getContributor().getName();
final String id = ext.getConfigurationElements()[j].getAttribute("typeid"); //$NON-NLS-1$
final String klass = ext.getConfigurationElements()[j].getAttribute("class"); //$NON-NLS-1$
registerFeature(bundleId, id, klass);
}
}
} catch (InvalidRegistryObjectException e) {
JSFCorePlugin.log(e, "Unable to read " + JSFCorePlugin.PLUGIN_ID + EXTPTID + " registry"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Create {@link IMetaDataEnabledFeatureExtension}s and add to registry
* @param bundleID
* @param typeId
* @param klass
*/
protected void registerFeature(String bundleID, String typeId, String klass){
IMetaDataEnabledFeatureExtension aFeature = new MetaDataEnabledFeatureExtension(bundleID, typeId, klass);
if (canCreateTypeForFeatureExtension(aFeature)){
if (!featuresMap.containsKey(typeId)){
List list = new ArrayList();
list.add(aFeature);
featuresMap.put(typeId, list);
}
else {
List list = featuresMap.get(typeId);
list.add(aFeature);
}
}
}
private boolean canCreateTypeForFeatureExtension(IMetaDataEnabledFeatureExtension feature) {
if (! typeCacheMap.containsKey(feature.getTypeID())){
IType type = AttributeValueRuntimeTypeRegistry.getInstance().getType(feature.getTypeID());
if (type != null){
Class typeClass = AttributeValueRuntimeTypeFactory.getInstance().getClassForType(type);
typeCacheMap.put(feature.getTypeID(), typeClass);
}
else
return false;
}
return typeCacheMap.get(feature.getTypeID()) != null;
}
/**
* @param typeId
* @return List of <code>AbstractMetaDataEnabledRuntimeTypeExtensions</code>
* for a given by type id
*
* TODO: make more efficient... no need to keep calculating features for subtypes.
*/
public List<IMetaDataEnabledFeatureExtension> getFeatures(String typeId) {
if (!featuresMap.containsKey(typeId))
featuresMap.put(typeId,new ArrayList());
//copy current featuresMapped to typeId into return list
List<IMetaDataEnabledFeatureExtension> srcList = featuresMap.get(typeId);
List<IMetaDataEnabledFeatureExtension> ret = new ArrayList<IMetaDataEnabledFeatureExtension>(srcList.size());
copy(ret, srcList);
List subs = getFeatureExtensionsForMatchingSubclass(typeId);
for (Iterator<IMetaDataEnabledFeatureExtension> it=subs.iterator();it.hasNext();){
IMetaDataEnabledFeatureExtension featureExt = it.next();
if (!ret.contains(featureExt))
ret.add(featureExt);
}
return ret;
}
private void copy(List<IMetaDataEnabledFeatureExtension> destList,
List<IMetaDataEnabledFeatureExtension> srcList) {
for (Iterator<IMetaDataEnabledFeatureExtension> it=srcList.iterator();it.hasNext();){
destList.add(it.next());
}
}
/**
* If the feature adapter is mapped to a type which is a superclass of the type of interest, then the feature adapter is an extension of that type
* @param typeId
* @return list of IMetaDataEnabledFeatureExtension
*/
private List<IMetaDataEnabledFeatureExtension> getFeatureExtensionsForMatchingSubclass(String typeId) {
IType type = AttributeValueRuntimeTypeRegistry.getInstance().getType(typeId);
Class typeClass = AttributeValueRuntimeTypeFactory.getInstance().getClassForType(type);
List<IMetaDataEnabledFeatureExtension> ret = new ArrayList<IMetaDataEnabledFeatureExtension>();
// loop thru all of the type classes mapped to feature adapters that are subclasses of the type
for (Iterator it=typeCacheMap.keySet().iterator();it.hasNext();){
String featureTypeId = (String)it.next();
Class featureTypeClass = typeCacheMap.get(featureTypeId);
try {
// if (featureTypeClass.equals(typeClass)){
// ret.add(featureTypeClass);
// }
// else
if (typeClass.asSubclass(featureTypeClass) != null) {
ret.addAll(featuresMap.get(featureTypeId));
}
} catch (ClassCastException e) {//
}
}
return ret;
}
}