blob: f0255d7a22ddd63c49632468b9ddd244482ea9fd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 Borland Software Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
* Christopher Gerking - bug 428620
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfException;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtilPlugin;
import org.eclipse.ocl.ecore.EcoreEnvironment;
import org.eclipse.osgi.util.NLS;
/** @author pkobiakov */
public class MetamodelRegistry {
public static boolean isMetamodelFileName(String fileName) {
return fileName.endsWith(".ecore") //$NON-NLS-1$
|| fileName.endsWith(".xcore") //$NON-NLS-1$
|| fileName.endsWith(".emof") //$NON-NLS-1$
|| fileName.endsWith(".oclinecore") //$NON-NLS-1$
;
}
public static final String MM_POINT_ID = "metamodelProvider"; //$NON-NLS-1$
private static final MetamodelRegistry ourInstance = new MetamodelRegistry();
private final IMetamodelProvider myMetamodelProvider;
private MetamodelRegistry() {
this(getDefaultMetamodelProvider());
}
public MetamodelRegistry(EPackage.Registry packageRegistry) {
this(getDefaultMetamodelProvider(packageRegistry));
}
public MetamodelRegistry(IMetamodelProvider metamodelProvider) {
myMetamodelProvider = metamodelProvider;
}
public EPackage.Registry toEPackageRegistry() {
return myMetamodelProvider.getPackageRegistry();
}
public static IMetamodelProvider getDefaultMetamodelProvider() {
return getDefaultMetamodelProvider(EPackage.Registry.INSTANCE);
}
public static IMetamodelProvider getDefaultMetamodelProvider(EPackage.Registry packageRegistry) {
return getDefaultMetamodelProvider(new EmfStandaloneMetamodelProvider(packageRegistry));
}
public static IMetamodelProvider getDefaultMetamodelProvider(IMetamodelProvider base) {
return EMFPlugin.IS_ECLIPSE_RUNNING ? Eclipse.getMetamodelProvider(base) : base;
}
public static MetamodelRegistry getInstance() {
return ourInstance;
}
public String[] getMetamodelIds() {
IMetamodelDesc[] metamodels = myMetamodelProvider.getMetamodels();
final Set<String> ids = new LinkedHashSet<String>(metamodels.length);
for(IMetamodelDesc desc : metamodels) {
ids.add(desc.getId());
}
return ids.toArray(new String[ids.size()]);
}
public static EPackage tryLookupEmptyRootPackage(String nsURI, EPackage.Registry registry) {
URI rootURI = URI.createURI(nsURI);
if(rootURI.segmentCount() == 0) {
return null;
}
String base = rootURI.segment(0);
String commonBaseURI = rootURI.trimSegments(rootURI.segmentCount()).appendSegment(base).toString().toLowerCase();
LinkedList<String> candidates = new LinkedList<String>();
for (String nextURI : registry.keySet()) {
if(nextURI.toLowerCase().startsWith(commonBaseURI)) {
candidates.add(nextURI);
}
}
// first attempt to select few packages which are likely
// to be child packages to avoid initialization of all packages
// in the registry
for(String nextNsURI : candidates) {
EPackage pack = null;
try {
pack = registry.getEPackage(nextNsURI);
}
catch(Throwable t) {
EmfUtilPlugin.log(t);
}
if (pack != null) {
pack = EmfUtil.getRootPackage(pack);
if (nsURI.equals(pack.getNsURI())) {
return pack;
}
}
}
// too greedy to check all packages
// // check all packages in the registry
// for(String nextNsURI : registry.keySet()) {
// EPackage pack = registry.getEPackage(nextNsURI);
//
// while (pack.getESuperPackage() != null) {
// pack = pack.getESuperPackage();
// }
//
// if (nsURI.equals(pack.getNsURI())) {
// return pack;
// }
// }
return null;
}
public IMetamodelDesc getMetamodelDesc(String id) throws EmfException {
IMetamodelDesc desc = myMetamodelProvider.getMetamodel(id);
// FIXME - hack for #35157
if(desc == null && id != null) {
for(IMetamodelDesc d: myMetamodelProvider.getMetamodels()) {
EPackage pack = d.getModel();
if (pack == null) {
continue;
}
if (id.equals(pack.getNsURI())) {
desc = d;
break;
}
pack = EmfUtil.getRootPackage(pack);
if (id.equals(pack.getNsURI())) {
desc = new EmfMetamodelDesc(pack, pack.getNsURI());
break;
}
}
}
// if (desc == null && id != null) {
// // Unregistered platform metamodels, e.g. available via "platform:/resource" or "platform:/plugin"
// URI uri = URI.createURI(id);
// if (uri.isPlatform()) {
// desc = MetamodelRegistry.createUndeclaredMetamodel(uri, id, resolutionRS != null ? resolutionRS : new ResourceSetImpl());
// }
// }
if (desc == null) {
throw new EmfException(NLS.bind(Messages.MetamodelRegistry_0, id, myMetamodelProvider.getMetamodels()));
}
return desc;
}
public static List<EPackage> resolveMetamodels(EPackage.Registry registry, List<String> packageName) {
final List<EPackage> metamodels = new UniqueEList<EPackage>(findPackages(registry, packageName));
if (metamodels.isEmpty()) {
metamodels.addAll(resolveUrilessMetamodels(registry, packageName));
}
return metamodels;
}
/**
* Special case for uriless ModelType registration like
* 'modeltype Ecore uses ecore;'
*/
private static List<EPackage> resolveUrilessMetamodels(EPackage.Registry registry, List<String> packageName) {
final List<EPackage> metamodels = new UniqueEList<EPackage>(1);
for(EPackage globalPack : findPackages(EPackage.Registry.INSTANCE, packageName)) {
// check if this global package is a valid finding
// i.e. if its root package is actually registered in the given registry
EPackage rootPack = EmfUtil.getRootPackage(globalPack);
EPackage registeredPack = null;
try {
registeredPack = registry.getEPackage(rootPack.getNsURI());
}
catch(Throwable t) {
EmfUtilPlugin.log(t);
}
if(registeredPack == rootPack) {
metamodels.add(globalPack);
}
}
return metamodels;
}
private static List<EPackage> findPackages(EPackage.Registry registry, List<String> packageName) {
final List<EPackage> metamodels = new UniqueEList<EPackage>(1);
// do not iterate over the key set itself to avoid concurrent modification
final List<String> keys = new ArrayList<String>(registry.keySet());
for (String nsURI : keys) {
EPackage pack = null;
try {
pack = registry.getEPackage(nsURI);
}
catch(Throwable t) {
EmfUtilPlugin.log(t);
}
if (pack == null || pack.getESuperPackage() != null) {
continue;
}
EPackage lookupPackage = lookupPackage(pack, packageName);
if (lookupPackage != null) {
metamodels.add(lookupPackage);
}
}
return metamodels;
}
public static EPackage lookupPackage(EPackage rootPackage, List<String> path) {
EPackage.Registry registry = new EPackageRegistryImpl();
registry.put(rootPackage.getNsURI(), rootPackage);
return EcoreEnvironment.findPackage(path, registry);
}
private static class Eclipse {
static IMetamodelProvider getMetamodelProvider(IMetamodelProvider base) {
if(base == null) {
throw new IllegalArgumentException();
}
IMetamodelProvider metamodelProvider = base;
IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor(EmfUtilPlugin.getDefault().getBundle().getSymbolicName(), MM_POINT_ID);
for (IConfigurationElement configElement : configElements) {
IMetamodelProvider provider = EclipseMetamodelProvider.Factory.create(configElement, metamodelProvider);
if (provider != null) {
metamodelProvider = provider;
}
}
return metamodelProvider;
}
}
}