blob: d781017f2e4e367dfe2dca57fef77ac82a3cd6d3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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:
******************************************************************************/
package org.eclipse.emf.ecp.common.model;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcorePackage;
/**
* MetaModelContext used by the editor to determine which model elements belong to the model.
*
* @author helming
*/
public abstract class AbstractECPMetaModelElementContext implements ECPMetaModelElementContext {
private Set<EClass> modelElementEClasses;
private static Set<EClass> guessedPackages;
/**
* {@inheritDoc}
*/
public boolean isNonDomainElement(EObject eObject) {
return isNonDomainElement(eObject.eClass());
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecp.model.MetaModelElementContext#isNonDomainElement(org.eclipse.emf.ecore.EClass)
*/
public abstract boolean isNonDomainElement(EClass eClass);
/**
* {@inheritDoc}
*/
public Set<EClass> getAllSubEClasses(EClass eClass, boolean association) {
return getAllSubEClasses(eClass, association, false);
}
/**
* {@inheritDoc}
*/
public Set<EClass> getAllSubEClasses(EClass eClass, boolean association, boolean includeNonDomainElements) {
Set<EClass> allEClasses = getAllModelElementEClasses(association, includeNonDomainElements);
Set<EClass> result = new HashSet<EClass>();
for (EClass subClass : allEClasses) {
if ((eClass.equals(EcorePackage.eINSTANCE.getEObject()) || eClass.isSuperTypeOf(subClass))
&& (!subClass.isAbstract()) && (!subClass.isInterface())) {
result.add(subClass);
}
}
return result;
}
/**
* {@inheritDoc}
*/
public Set<EClass> getAllModelElementEClasses(boolean association) {
return getAllModelElementEClasses(association, false);
}
/**
* {@inheritDoc}
*/
public Set<EClass> getAllModelElementEClasses(boolean association, boolean includeNonDomainElemnts) {
Set<EClass> result = new HashSet<EClass>();
for (EClass subClass : getAllModelElementEClassesImpl()) {
if (association || !isAssociationClassElement(subClass)) {
if (includeNonDomainElemnts || !isNonDomainElement(subClass)) {
result.add(subClass);
}
}
}
return result;
}
/**
* @param newMEInstance {@link EObject} the new modelElement instance.
* @return EReference the Container
* @param parent The EObject to get containment references from
*/
public EReference getPossibleContainingReference(final EObject newMEInstance, EObject parent) {
// the value of the 'EAll Containments' reference list.
List<EReference> eallcontainments = parent.eClass().getEAllContainments();
EReference reference = null;
for (EReference containmentitem : eallcontainments) {
EClass eReferenceType = containmentitem.getEReferenceType();
if (eReferenceType.equals(newMEInstance)) {
reference = containmentitem;
break;
} else if (eReferenceType.equals(EcorePackage.eINSTANCE.getEObject())
|| eReferenceType.isSuperTypeOf(newMEInstance.eClass())) {
reference = containmentitem;
break;
}
}
return reference;
}
/**
* {@inheritDoc}
*/
public boolean isGuessed() {
IConfigurationElement[] packages = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.eclipse.emf.ecp.model.ecppackage");
return (packages.length == 0);
}
/**
* Returns all types of model elements in this context.
*
* @return a set of {@link EClass}es
*/
protected Set<EClass> getAllModelElementEClassesImpl() {
if (modelElementEClasses != null) {
return new HashSet<EClass>(modelElementEClasses);
}
Set<EClass> result = new HashSet<EClass>();
Set<String> registeredPackages = new HashSet<String>();
Registry registry = EPackage.Registry.INSTANCE;
IConfigurationElement[] packages = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.eclipse.emf.ecp.model.ecppackage");
for (IConfigurationElement element : packages) {
String packageName = element.getAttribute("modelPackage");
registeredPackages.add(packageName);
}
if (registeredPackages.isEmpty()) {
return guessPackages(new HashSet<Entry<String, Object>>(registry.entrySet()));
}
for (Entry<String, Object> entry : new HashSet<Entry<String, Object>>(registry.entrySet())) {
if (!registeredPackages.contains(entry.getKey())) {
continue;
}
try {
EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(entry.getKey());
result.addAll(getAllModelElementEClasses(ePackage));
}
// BEGIN SUPRESS CATCH EXCEPTION
catch (RuntimeException exception) {
// END SUPRESS CATCH EXCEPTION
String message = "Failed to load model package " + entry.getKey();
Activator.getDefault().logException(message, exception);
}
}
modelElementEClasses = result;
return result;
}
private Set<EClass> guessPackages(HashSet<Entry<String, Object>> entries) {
if (guessedPackages == null) {
guessedPackages = new HashSet<EClass>();
for (Entry<String, Object> entry : entries) {
if (!isKnownPackage(entry.getKey())) {
// This is used to discover known packages which can be added to
// know packages then.
// System.out.println("\"" + entry.getKey() + "\"" + ",");
try {
EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(entry.getKey());
guessedPackages.addAll(getAllModelElementEClasses(ePackage));
// BEGIN SUPRESS CATCH EXCEPTION
} catch (RuntimeException e) {
// END SUPRESS CATCH EXCEPTION
String message = "Failed to load model package: " + entry.getKey();
Activator.getDefault().logWarning(message, e);
}
}
}
}
return guessedPackages;
}
private boolean isKnownPackage(String key) {
String[] elements = { "http://www.eclipse.org/m2t/xpand/Trace",
"http://www.eclipse.org/emf/eef/mapping/filters/1.0.0", "http://www.cs.tum.edu/cope/history/0.1.42",
"http://www.eclipse.org/acceleo/profiler/3.0", "http://www.eclipse.org/emf/compare/epatch/0.1",
"http://www.eclipse.org/ocl/1.1.0/UML", "http://www.eclipse.org/emf/eef/components/1.0.0",
"http://www.eclipse.org/amalgamation/discovery/1.0", "http://www.eclipse.org/emf/compare/match/1.1",
"http://www.eclipse.org/emf/eef/views/1.0.0",
"http://www.eclipse.org/gmf/examples/runtime/1.0.0/logicsemantic",
"http://www.eclipse.org/acceleo/mtl/3.0", "http://www.eclipse.org/acceleo/mt/2.6.0/statements",
"http://www.eclipse.org/acceleo/traceability/1.0", "http://www.eclipse.org/acceleo/mt/2.6.0",
"http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0",
"http://www.cs.tum.edu/cope/migration/test", "http://www.eclipse.org/uml2/1.1.0/GenModel",
"http://www.eclipse.org/acceleo/mt/2.6.0/expressions", "http://www.eclipse.org/acceleo/mtl/3.0/",
"http://www.eclipse.org/emf/CDO/Eresource/2.0.0",
"http://www.eclipse.org/emf/eef/mapping/navigation/1.0.0",
"http://www.eclipse.org/emf/eef/views/toolkits/1.0.0", "http://www.eclipse.org/acceleo/mtl/cst/3.0",
"http://www.eclipse.org/emf/eef/generation/1.0.0", "http://www.eclipse.org/emf/2009/Validation",
"http://www.eclipse.org/emf/eef/mapping/1.0.0", "http://www.eclipse.org/emf/compare/diff/1.1",
"http://www.eclipse.org/acceleo/mt/2.6.0/core", "http://www.eclipse.org/gmf/2008/mappings",
"http://www.w3.org/XML/1998/namespace", "http://www.eclipse.org/ocl/1.1.0/OCL",
"http://www.eclipse.org/ocl/1.1.0/OCL/Expressions", "http://www.eclipse.org/emf/2002/GenModel",
"http://www.eclipse.org/qvt/1.0/ImperativeOCL", "http://unicase.org/emfstore/esmodel",
"http://www.cs.tum.edu/cope/migration", "http://unicase.org/esmodel/accesscontrol/roles",
"http:///com/ibm/etools/dtd.ecore", "http:///www.eclipse.org/m2m/qvt/operational/trace.ecore",
"http://www.eclipse.org/qvt/1.0.0/Operational/Expressions", "http://www.eclipse.org/gmf/2006/GenModel",
"http://www.eclipse.org/uml2/3.0.0/UML", "http://www.eclipse.org/uml2/2.0.0/UML",
"http://www.eclipse.org/gmf/runtime/1.0.0/notation", "http://www.eclipse.org/emf/2002/Tree",
"http://www.eclipse.org/OCL2/1.0.0/ocl/uml", "http://www.eclipse.org/OCL2/1.0.0/ocl/types",
"http://unicase.org/esmodel/versioning/events", "http://www.eclipse.org/emf/2003/Change",
"http://www.eclipse.org/OCL2/1.0.0/ocl/query", "http://www.eclipse.org/gmf/2006/Trace",
"http://www.eclipse.org/QVT2/1.0.0/Operational/cst", "http://unicase.org/esmodel/accesscontrol",
"http://www.eclipse.org/emf/2005/Ecore2XML", "http://unicase.org/esmodel/versioning/operations",
"http://www.eclipse.org/emf/2002/Ecore", "http://www.eclipse.org/QVT2/1.0.0/Operational/cst/temp",
"http://www.eclipse.org/gmf/2005/GenModel/2.0", "http://www.eclipse.org/gmf/2005/ToolDefinition",
"http://unicase.org/esmodel/versioning", "http://www.cs.tum.edu/cope/declaration",
"http://www.eclipse.org/gmf/2005/GenModel", "http://www.eclipse.org/gmf/2005/mappings",
"http://unicase.org/workspace", "http://www.eclipse.org/gmf/2006/GraphicalDefinition",
"http://www.eclipse.org/gmf/runtime/1.0.1/notation", "http://www.eclipse.org/emf/2003/XMLType",
"http://www.eclipse.org/uml2/2.1.0/UML", "http://www.eclipse.org/gmf/2005/mappings/2.0",
"http://www.eclipse.org/ocl/1.1.0/OCL/Types", "http://www.eclipse.org/QVT/1.0.0/Operational",
"http://www.eclipse.org/gmf/runtime/1.0.2/notation", "http://www.eclipse.org/ocl/1.1.0/OCL/Utilities",
"moduleCore.xmi", "http://www.eclipse.org/emf/2002/XSD2Ecore", "http://unicase.org/workspaceModel",
"http://www.eclipse.org/emf/2004/Ecore2Ecore", "http://www.eclipse.org/gmf/2005/GraphicalDefinition",
"http://www.eclipse.org/gmf/2009/GenModel", "http://www.eclipse.org/xsd/2002/XSD",
"http://www.eclipse.org/emf/2002/Mapping", "http://unicase.org/metamodel",
"http://www.eclipse.org/gmf/2008/GenModel", "DTD.xmi", "http://www.eclipse.org/ocl/1.1.0/OCL/CST",
"http://www.eclipse.org/OCL2/1.0.0/ocl/expressions", "componentcore.xmi",
"http://www.eclipse.org/ocl/1.1.0/Ecore", "http://unicase.org/esmodel/notification",
"http://www.eclipse.org/OCL2/1.0.0/oclstdlib", "http://unicase.org/esmodel/versioning/events/server/",
"http://unicase.org/emfstore/esmodel/url", "http://www.eclipse.org/gmf/2006/mappings",
"http://www.eclipse.org/OCL2/1.0.0/ocl", "http://unicase.org/esmodel/versioning/operations/semantic",
"http://www.eclipse.org/OCL2/1.0.0/ocl/utilities", "http://www.eclipse.org/uml2/2.2.0/GenModel",
"http://eclipse.org/emf/emfstore/server/model/versioning", "http://eclipse.org/emf/emfstore/server/model/url",
"http://eclipse.org/emf/emfstore/client/model", "urn:model.ecore", "http://eclipse.org/emf/emfstore/server/model/notification",
"http://eclipse.org/emf/ecp/common/model/workspaceModel", "http://eclipse.org/emf/emfstore/server/model/versioning/events",
"http://eclipse.org/emf/emfstore/server/model/roles", "http://eclipse.org/emf/emfstore/server/model/versioning/operations",
"http://eclipse.org/emf/emfstore/server/model/versioning/events/server/", "http://eclipse.org/emf/emfstore/server/model",
"http://eclipse.org/emf/emfstore/server/model/accesscontrol", "http://eclipse.org/emf/emfstore/common/model",
"http://eclipse.org/emf/emfstore/server/model/versioning/operations/semantic",
"http://www.eclipse.org/emf/edapt/declaration/0.3",
"http://www.eclipse.org/emf/edapt/history/0.3",
"http://www.eclipse.org/emf/edapt/migration/0.3" };
Set<String> knownPackages = new HashSet<String>(Arrays.asList(elements));
return knownPackages.contains(key);
}
/**
* Retrieve all EClasses from the Ecore package that are model element subclasses.
*
* @param ePackage the package to get the classes from
* @return a set of EClasses
*/
private static Set<EClass> getAllModelElementEClasses(EPackage ePackage) {
Set<EClass> result = new HashSet<EClass>();
for (EPackage subPackage : ePackage.getESubpackages()) {
result.addAll(getAllModelElementEClasses(subPackage));
}
for (EClassifier classifier : ePackage.getEClassifiers()) {
if (classifier instanceof EClass) {
EClass subEClass = (EClass) classifier;
result.add(subEClass);
}
}
return result;
}
}