| /******************************************************************************* |
| * 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; |
| } |
| |
| |
| } |