blob: 2db78141a939e2b5b31596f1431b0863d4dae222 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2010 BMW Car IT, Technische Universitaet Muenchen, and others.
* 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:
* BMW Car IT - Initial API and implementation
* Technische Universitaet Muenchen - Major refactoring and extension
*******************************************************************************/
package org.eclipse.emf.edapt.internal.common;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.Diagnostician;
/**
* Helper class to administer the extent of a metamodel (root packages, class
* extents, ...)
*
* @author herrmama
* @author $Author$
* @version $Rev$
* @levd.rating RED Rev:
*/
public class MetamodelExtent {
/**
* Class extent
*/
private final Map<EClass, Collection<EObject>> extentMap;
/**
* Root packages
*/
private Collection<EPackage> rootPackages;
/**
* Constructor
*/
@SuppressWarnings("unchecked")
public MetamodelExtent() {
this(Collections.EMPTY_LIST);
}
/**
* Constructor
*/
public MetamodelExtent(Collection<EPackage> rootPackages) {
this.rootPackages = new ArrayList<EPackage>();
extentMap = new IdentityHashMap<EClass, Collection<EObject>>();
addRootPackages(rootPackages);
}
/*
* ------------- Root packages -------------
*/
/**
* Add a root package
*
* @param rootPackage
* Root package
*/
public void addRootPackage(EPackage rootPackage) {
addRootPackages(Arrays.asList(rootPackage));
}
/**
* Set the collection of root packages
*
* @param rootPackages
* Collection of root packages
*/
public void setRootPackages(Collection<EPackage> rootPackages) {
this.rootPackages.clear();
addRootPackages(rootPackages);
}
/**
* Add a collection of root packages
*
* @param rootPackages
* Collection of root packages
*/
public void addRootPackages(Collection<EPackage> rootPackages) {
for (final EPackage rootPackage : rootPackages) {
if (!this.rootPackages.contains(rootPackage)) {
this.rootPackages.add(rootPackage);
}
}
clearExtentMap();
}
/**
* Getter for the root packages
*
* @return Collection of root packages
*/
public Collection<EPackage> getRootPackages() {
return rootPackages;
}
/*
* ---------- Extent map ----------
*/
/**
* Get the extent of a certain type
*
* @param type
* Type
* @return Collection of objects
*/
public Collection<EObject> getChoiceOfValues(EClass type) {
initExtentMap();
final Collection<EObject> collection = extentMap.get(type);
return collection == null ? Collections.<EObject> emptySet()
: collection;
}
/**
* Add a collection of metamodel elements to the extent
*/
public void addToExtent(Collection<EObject> elements) {
for (final EObject element : elements) {
addToExtent(element);
}
}
/**
* Add a metamodel element to the extent
*/
public void addToExtent(EObject element) {
final EClass eClass = element.eClass();
add(element, eClass);
for (final EClass superClass : eClass.getEAllSuperTypes()) {
add(element, superClass);
}
if (element instanceof EPackage && element.eContainer() == null) {
if (!rootPackages.contains(element)) {
addRootPackage((EPackage) element);
}
}
}
/**
* Add a metamodel element to the extent for a certain class (helper method)
*/
private void add(EObject element, EClass eClass) {
Collection<EObject> collection = extentMap.get(eClass);
if (collection == null) {
collection = new HashSet<EObject>();
extentMap.put(eClass, collection);
}
collection.add(element);
}
/**
* Remove a collection of element from the extent
*
* @param elements
* Collection of objects
*/
public void removeFromExtent(Collection<EObject> elements) {
for (final EObject element : elements) {
removeFromExtent(element);
}
}
/**
* Remove a metamodel element from the extent
*/
public void removeFromExtent(EObject element) {
final EClass eClass = element.eClass();
remove(element, eClass);
for (final EClass superClass : eClass.getEAllSuperTypes()) {
remove(element, superClass);
}
}
/**
* Remove a metamodel element from the extent for a certain clas (helper
* method)
*/
private void remove(EObject element, EClass eClass) {
final Collection<EObject> collection = extentMap.get(eClass);
collection.remove(element);
if (collection.isEmpty()) {
extentMap.remove(collection);
}
}
/**
* Perform a full recalculation of the extent map starting from the root
* packages
*/
private void initExtentMap() {
if (extentMap.isEmpty()) {
for (final EClassifier classifier : EcorePackage.eINSTANCE
.getEClassifiers()) {
if (classifier instanceof EDataType) {
addToExtent(classifier);
}
}
for (final EPackage rootPackage : rootPackages) {
addToExtent(rootPackage);
for (final Iterator<EObject> i = rootPackage.eAllContents(); i
.hasNext();) {
final EObject element = i.next();
addToExtent(element);
}
}
}
}
/**
* Dispose the extent
*/
public void dispose() {
clearExtentMap();
rootPackages = null;
}
/**
* Clear the extent map
*/
public void clearExtentMap() {
extentMap.clear();
}
/**
* Determine whether the metamodel is consistent, i.e. fulfills the
* constraints defined by the meta-metamodel
*
* @return true if it is consistent, false otherwise
*/
public boolean isConsistent() {
final BasicDiagnostic diagnostic = new BasicDiagnostic();
final Diagnostician diagnostician = new Diagnostician();
for (final EPackage p : getRootPackages()) {
diagnostician.validate(p, diagnostic);
}
return diagnostic.getSeverity() == Diagnostic.OK
|| diagnostic.getSeverity() == Diagnostic.WARNING;
}
}