/*
* Copyright (c) 2003- michael lawley and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation
* which accompanies this distribution, and is available by writing to
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Contributors:
* michael lawley
*
*
*/
package tefkat.model.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.TreeIterator;
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.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.ecore.XSDEcoreBuilder;
/**
* Some generic functions for interacting with Tefkat transformations and models.
*
* @author lawley
*
*/
public abstract class ModelUtils {
public final static String getFullyQualifiedName(Class klass) {
return klass.getName();
}
public final static String getFullyQualifiedName(EClassifier eClassifier) {
return getFullyQualifiedName(eClassifier.getEPackage()) + "::" + eClassifier.getName();
}
final static protected String getFullyQualifiedName(EPackage ePackage) {
String name = "";
while (null != ePackage) {
name = "::" + ePackage.getName() + name;
ePackage = ePackage.getESuperPackage();
}
return name;
}
public final static String getFullyQualifiedName(EStructuralFeature eFeature) {
return getFullyQualifiedName(eFeature.getEContainingClass()) + "." + eFeature.getName();
}
/**
* @param node
* @param klass
* @param featureName
* @return @throws
* ResolutionException
*/
final public static EStructuralFeature getFeature(EClass klass, String featureName) {
EStructuralFeature feature = klass.getEStructuralFeature(featureName);
if (null == feature) {
String featureNames = null;
List allFeatures = klass.getEAllStructuralFeatures();
for (Iterator itr = allFeatures.iterator(); itr.hasNext();) {
EStructuralFeature esf = (EStructuralFeature) itr.next();
if (null == featureNames) {
featureNames = esf.getName();
} else {
featureNames = featureNames + ", " + esf.getName();
}
}
throw new RuntimeException("Cannot find feature '"
+ featureName + "' for '" + klass.getName()
+ ". Valid features are: " + featureNames);
}
return feature;
}
/**
* Lookup the supplied name map (containing both unqualifed and fully-qualified names) for the corresponding EClass.
* Returns null if it is not found.
*
* @param nameMap
* @param name
* @return
*/
public final static EClassifier findClassifierByName(Map nameMap, String name) {
if (!nameMap.containsKey(name)) {
return null;
}
Object obj = nameMap.get(name);
if (obj instanceof List) {
final StringBuilder sb = new StringBuilder();
sb.append("Ambiguous name: ")
.append(name)
.append(" resolves to [");
for (final Iterator itr = ((List) obj).iterator(); itr.hasNext(); ) {
EClassifier classifier = (EClassifier) itr.next();
sb.append(getFullyQualifiedName(classifier));
sb.append(" (").append(classifier.getEPackage().getNsURI()).append(")");
if (itr.hasNext()) {
sb.append(", ");
}
}
sb.append("]");
throw new RuntimeException(sb.toString());
}
return (EClassifier) obj;
}
/**
* Given a set of EPackages, build a Map of
* names to EClasses using both the unqualified and fully-qualified names.
*
* If there is a name clash, put null in the map.
*
*/
public final static Map buildPackageNameMaps(Collection packages, Map nameMap, String namespace) {
for (final Iterator pkgItr = packages.iterator(); pkgItr.hasNext(); ) {
EPackage pkg = (EPackage) pkgItr.next();
for (Iterator itr = pkg.getEClassifiers().iterator(); itr.hasNext(); ) {
EClassifier eClassifier = (EClassifier) itr.next();
String fqName = ModelUtils.getFullyQualifiedName(eClassifier);
addToMap(nameMap, fqName, eClassifier);
String name = eClassifier.getName();
addToMap(nameMap, name, eClassifier);
if (null != namespace) {
addToMap(nameMap, '^' + namespace + fqName, eClassifier);
addToMap(nameMap, namespace + '^' + name, eClassifier);
}
}
buildPackageNameMaps(pkg.getESubpackages(), nameMap, namespace);
}
return nameMap;
}
/**
* Given a set of resources containing EPackages and EClasses, build a Map of
* names to EClasses using both the unqualified and fully-qualified names.
*
* If there is a name clash, put null in the map.
*
* @param resources
* @return
*/
// public final static Map buildNameMaps(Collection resources, String namespace) {
// return buildNameMaps(resources, new HashMap(), namespace);
// }
// public final static Map buildNameMaps(Collection resources, Map nameMap, String namespace) {
// XSDEcoreBuilder xsdEcoreBuilder = null;
// for (Iterator itr = resources.iterator(); itr.hasNext();) {
// Resource res = (Resource) itr.next();
// // Do a tree iteration over the Resource, pruning on every
// // non-EPackage since only EPackages can (transitively) contain
// // EClassifiers
// TreeIterator treeItr = res.getAllContents();
// xsdEcoreBuilder = buildNameMaps(treeItr, nameMap, namespace, res.getResourceSet(), xsdEcoreBuilder);
// }
// if (null != xsdEcoreBuilder) {
// for (Iterator itr = xsdEcoreBuilder.getTargetNamespaceToEPackageMap().values().iterator(); itr.hasNext();) {
// EPackage pkg = (EPackage) itr.next();
// xsdEcoreBuilder = buildNameMaps(pkg.eAllContents(), nameMap, namespace, null, xsdEcoreBuilder);
// }
// }
//
// return nameMap;
// }
private static XSDEcoreBuilder buildNameMaps(TreeIterator treeItr, Map nameMap, String namespace, final ResourceSet resourceSet, XSDEcoreBuilder xsdEcoreBuilder) {
while (treeItr.hasNext()) {
EObject obj = (EObject) treeItr.next();
if (obj instanceof EClassifier) {
EClassifier eClassifier = (EClassifier) obj;
String fqName = ModelUtils.getFullyQualifiedName(eClassifier);
addToMap(nameMap, fqName, eClassifier);
String name = eClassifier.getName();
addToMap(nameMap, name, eClassifier);
if (null != namespace) {
addToMap(nameMap, '^' + namespace + fqName, eClassifier);
addToMap(nameMap, namespace + '^' + name, eClassifier);
}
// if (obj instanceof EEnum) {
// EEnum eEnum = (EEnum) obj;
// for (Iterator eItr = eEnum.getELiterals().iterator(); eItr.hasNext(); ) {
// EEnumLiteral eLiteral = (EEnumLiteral) eItr.next();
// nameMap.put(fqName + "::" + eLiteral.getName(), eLiteral);
// }
// }
} else if (obj instanceof XSDSchema) {
// Attempt to handle ecore models dynamically generated from xml schema
if (null == xsdEcoreBuilder) {
xsdEcoreBuilder = new XSDEcoreBuilder();
}
try {
xsdEcoreBuilder.generate((XSDSchema) obj);
} catch (ClassCastException e) {
// FIXME ignore this for the moment -- it's patched in EMF's CVS HEAD
// see bugzilla -- https://bugs.eclipse.org/bugs/show_bug.cgi?id=136267
System.err.println(obj);
//e.printStackTrace();
}
}
if (!(obj instanceof EPackage)) {
treeItr.prune();
}
}
return xsdEcoreBuilder;
}
private static void addToMap(Map nameMap, String name, EClassifier eClassifier) {
if (nameMap.containsKey(name)) {
if (!eClassifier.equals(nameMap.get(name))) {
// Record a name-clash by storing a List of the clashing things
Object clashObj = nameMap.get(name);
if (clashObj instanceof List) {
((List) clashObj).add(eClassifier);
} else {
List allNames = new ArrayList();
allNames.add((EClassifier) clashObj);
allNames.add(eClassifier);
nameMap.put(name, allNames);
}
}
} else {
nameMap.put(name, eClassifier);
}
}
// public static void resolveTrackingClassNames(Transformation t, Map nameMap)
// throws TefkatException {
// for (Iterator itr = t.getPatternDefn().iterator(); itr.hasNext(); ) {
// PatternDefn pDefn = (PatternDefn) itr.next();
// resolveTrackingClassNames(pDefn.getTerm(), nameMap);
// }
// for (Iterator itr = t.getTRule().iterator(); itr.hasNext(); ) {
// TRule tRule = (TRule) itr.next();
// resolveTrackingClassNames(tRule.getSrc(), nameMap);
// resolveTrackingClassNames(tRule.getTgt(), nameMap);
// }
// }
//
// private static void resolveTrackingClassNames(List terms, Map nameMap)
// throws TefkatException {
// for (Iterator itr = terms.iterator(); itr.hasNext(); ) {
// Term term = (Term) itr.next();
// resolveTrackingClassNames(term, nameMap);
// }
// }
//
// private static void resolveTrackingClassNames(Term term, Map nameMap)
// throws TefkatException {
// if (term instanceof TrackingUse) {
// TrackingUse trackingUse = (TrackingUse) term;
// String tname = trackingUse.getTrackingName();
// EClassifier tracking = findClassifierByName(nameMap, tname);
// if (null == tracking) {
// throw new TefkatException("Undefined tracking class: " + tname);
// }
// if (!(tracking instanceof EClass)) {
// String type = (tracking instanceof EDataType) ? "an EDataType" :
// (tracking instanceof EEnum) ? "an EEnum" :
// "a " + tracking.getClass().getName();
// throw new TefkatException("Expected an EClass: " + tname + ", found " + type);
// }
// trackingUse.setTracking((EClass) tracking);
// } else if (term instanceof CompoundTerm) {
// CompoundTerm compoundTerm = (CompoundTerm) term;
// resolveTrackingClassNames(compoundTerm.getTerm(), nameMap);
// }
// }
}