/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * 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: * Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.infra.extendedtypes; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.gmf.runtime.emf.type.core.ClientContextManager; import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry; import org.eclipse.gmf.runtime.emf.type.core.IClientContext; import org.eclipse.gmf.runtime.emf.type.core.IElementType; import org.eclipse.gmf.runtime.emf.type.core.ISpecializationType; import org.eclipse.papyrus.infra.extendedtypes.preferences.ExtendedTypesPreferences; import org.eclipse.papyrus.infra.extendedtypes.types.ExtendedHintedTypeFactory; import org.osgi.framework.Bundle; /** * Registry for all extended types. */ public class ExtendedTypesRegistry { /** private singleton instance */ private static ExtendedTypesRegistry registry; /** list of retrieved extended type sets */ protected List<ExtendedElementTypeSet> extendedTypeSets = null; /** unique resource set to load all extended types models */ protected ResourceSet extendedTypesResourceSet = null; /** * Private constructor. */ private ExtendedTypesRegistry() { } /** * returns the singleton instance of this registry * * @return the singleton instance of this registry */ public static synchronized ExtendedTypesRegistry getInstance() { if(registry == null) { registry = new ExtendedTypesRegistry(); registry.init(); } return registry; } /** * Inits the registry. */ protected void init() { // 0. Reset the values extendedTypesResourceSet = null; extendedTypeSets = null; // 1. create the resource set extendedTypesResourceSet = createResourceSet(); // 2. create the list only when registry is acceded for the first time extendedTypeSets = loadExtendedTypeSets(); } /** * Retrieves and loads extended type sets registered in the platform. It should also load configuration sets from the workspace. */ protected List<ExtendedElementTypeSet> loadExtendedTypeSets() { List<ExtendedElementTypeSet> extendedElementTypeSets = new ArrayList<ExtendedElementTypeSet>(); // 1. retrieve from the workspace // TODO implement retrieve from workspace // 2. retrieve from the platform. List<ExtendedElementTypeSet> registeredSets = loadExtendedTypeSetsFromPlatform(); if(registeredSets != null && !registeredSets.isEmpty()) { extendedElementTypeSets.addAll(registeredSets); } return extendedElementTypeSets; } /** * Creates the resource set that contains all models for extended types * * @return the resource set newly created. */ protected ResourceSet createResourceSet() { ResourceSet set = new ResourceSetImpl(); return set; } /** * Loads the extensions in the platform * * @return the list of extension registered in the platform */ protected List<ExtendedElementTypeSet> loadExtendedTypeSetsFromPlatform() { List<ExtendedElementTypeSet> platformElementTypeSets = new ArrayList<ExtendedElementTypeSet>(); IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(IExtendedTypeExtensionPoint.EXTENSION_POINT_ID); // for each element, parses and retrieve the model file. then loads it and returns the root element for(IConfigurationElement element : elements) { String modelPath = element.getAttribute(IExtendedTypeExtensionPoint.PATH); String extendedTypeSetId = element.getAttribute(IExtendedTypeExtensionPoint.ID); String contributorID = element.getContributor().getName(); if(Platform.inDebugMode()) { Activator.log.debug("[Reading extension point]"); Activator.log.debug("- Path to the model: " + modelPath); Activator.log.debug("- id of the container bundle: " + contributorID); Activator.log.debug("- id of the extended type set: " + extendedTypeSetId); } ExtendedElementTypeSet set = getExtendedElementTypeSet(extendedTypeSetId, modelPath, contributorID); if(set != null) { platformElementTypeSets.add(set); } } return platformElementTypeSets; } /** * <p> * Loads the resource containing the extended element type set model. * </p> * <p> * It looks the model file in the fragments first, then in the plugin itself.<BR> * If this is already a fragment, it should look in the fragment only * </p> * * @param extendedTypesID * id of the extended type set to load * @param modelPath * path of the model in the bundle * @param bundleId * id of the bundle containing the model file * @return the loaded file or <code>null</code> if some problem occured during loading */ protected ExtendedElementTypeSet getExtendedElementTypeSet(String extendedTypesID, String modelPath, String bundleId) { // 1. look in preferences. String filePath = ExtendedTypesPreferences.getExtendedTypesRedefinition(extendedTypesID); if(filePath != null) { getExtendedElementTypeSetInPluginStateArea(extendedTypesID); } // 2. no local redefinition. Load extended type set from plugin definition Bundle bundle = Platform.getBundle(bundleId); if(Platform.isFragment(bundle)) { return getExtendedElementTypeSetInBundle(modelPath, bundleId); } else { // this is a plugin. Search in sub fragments, then in the plugin Bundle[] fragments = Platform.getFragments(bundle); // no fragment, so the file should be in the plugin itself if(fragments == null) { return getExtendedElementTypeSetInBundle(modelPath, bundleId); } else { for(Bundle fragment : fragments) { ExtendedElementTypeSet extendedElementTypeSet = getExtendedElementTypeSetInBundle(modelPath, fragment.getSymbolicName()); if(extendedElementTypeSet != null) { return extendedElementTypeSet; } } // not found in fragments. Look in the plugin itself return getExtendedElementTypeSetInBundle(modelPath, bundleId); } } } /** * Retrieves the contribution in the plugin area * * @param path * the path of the element type set to load in the plugin area */ protected ExtendedElementTypeSet getExtendedElementTypeSetInPluginStateArea(String path) { // read in preferences area IPath resourcePath = Activator.getDefault().getStateLocation().append(path); URI uri = URI.createFileURI(resourcePath.toOSString()); if(uri != null && uri.isFile()) { Resource resource = extendedTypesResourceSet.createResource(uri); try { resource.load(null); } catch (IOException e) { return null; } EObject content = resource.getContents().get(0); if(content instanceof ExtendedElementTypeSet) { return (ExtendedElementTypeSet)content; } Activator.log.error("Impossible to cast the object into an ExtendedElementTypeSet: " + content, null); return null; } return null; } /** * * @param modelPath * path of the model in the bundle * @param bundleId * id of the bundle containing the model file * @return the loaded file or <code>null</code> if some problem occured during loading */ protected ExtendedElementTypeSet getExtendedElementTypeSetInBundle(String modelPath, String bundleID) { Resource resource = extendedTypesResourceSet.createResource(URI.createPlatformPluginURI(bundleID + Path.SEPARATOR + modelPath, true)); try { resource.load(null); } catch (IOException e) { return null; } EObject content = resource.getContents().get(0); if(content instanceof ExtendedElementTypeSet) { return (ExtendedElementTypeSet)content; } Activator.log.error("Impossible to cast the object into an ExtendedElementTypeSet: " + content, null); return null; } /** * Gets the element type for <code>id</code>. May return <code>null</code> if this element is not registered. * * @param id * the type ID * @return the registered type with this ID, or <code>null</code> if there * is none. */ public IElementType getType(String id) { // 1. checks if the element already exists IElementType type = ElementTypeRegistry.getInstance().getType(id); // 2. If it exists, returns it as usual if(type != null) { return type; } // 3. It does not exists. It could be retrieve in the extended type sets for(ExtendedElementTypeSet set : extendedTypeSets) { for(ExtendedElementTypeConfiguration elementTypeConfiguration : set.getElementType()) { if(id.equals(elementTypeConfiguration.getId())) { // create and add in the standard registry the required element type from its configuration @SuppressWarnings("restriction") ISpecializationType createSpecializationType = ExtendedHintedTypeFactory.getInstance().createSpecializationType(new ExtendedSemanticTypeDescriptor(elementTypeConfiguration)); // register it, so it should be accessible next time ElementTypeRegistry.getInstance().register(createSpecializationType); // retrieve papyrus client context and add the registered type to this context IClientContext papyrusContext = ClientContextManager.getInstance().getClientContext("org.eclipse.papyrus.infra.services.edit.TypeContext"); if(papyrusContext != null) { papyrusContext.bindId(id); } return createSpecializationType; } } } return null; } }