/*
* Copyright (c) 2004- 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.engine;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.GenericXMLResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.xsd.util.XSDResourceFactoryImpl;
import tefkat.config.TefkatConfig.ExecutionMode;
import tefkat.config.TefkatConfig.Model;
import tefkat.config.TefkatConfig.TransformationTask;
import tefkat.model.PatternScope;
import tefkat.model.Query;
import tefkat.model.ReferenceExtent;
import tefkat.model.Var;
import tefkat.model.ContainerExtent;
import tefkat.model.Extent;
import tefkat.model.NamespaceDeclaration;
import tefkat.model.TefkatException;
import tefkat.model.TefkatFactory;
import tefkat.model.Transformation;
import tefkat.model.impl.TefkatPackageImpl;
import tefkat.model.internal.IntMap;
import tefkat.model.internal.ModelUtils;
import tefkat.model.parser.ParserListener;
import tefkat.model.parser.TefkatResourceFactory;
/**
* @author lawley
*
*/
public class Tefkat {
static {
// Ensure EMF runtime knows about the Tefkat metamodel
TefkatPackageImpl.init();
}
private static final Map SERIALIZATION_OPTIONS;
static {
SERIALIZATION_OPTIONS = new HashMap();
SERIALIZATION_OPTIONS.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
SERIALIZATION_OPTIONS.put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
}
private ResourceSet _resourceSet;
private final List engineListeners = new ArrayList();
private final Resource.Factory XMI_RESOURCE_FACTORY = new XMIResourceFactoryImpl();
private final TefkatResourceFactory TEFKAT_RESOURCE_FACTORY = new TefkatResourceFactory();
private final Resource.Factory XSD_RESOURCE_FACTORY = new XSDResourceFactoryImpl();
private final Resource.Factory ECORE_RESOURCE_FACTORY = new EcoreResourceFactoryImpl();
private final Resource.Factory XML_RESOURCE_FACTORY = new GenericXMLResourceFactoryImpl();
private final Map functions = new HashMap();
private transient boolean isRunning = false;
private RuleEvaluator ruleEvaluator;
private boolean isIncremental = true;
private boolean printingStats = false;
private boolean paused;
private List threads = new ArrayList();
final private Adapter resourceLoadListener = new AdapterImpl() {
public void notifyChanged(Notification notif) {
if (Notification.SET == notif.getEventType() &&
notif.getNotifier() instanceof Resource &&
Resource.RESOURCE__IS_LOADED == notif.getFeatureID(Resource.class) &&
notif.getNewBooleanValue()) {
Resource res = (Resource) notif.getNotifier();
fireResourceLoaded(res);
res.eAdapters().remove(resourceLoadListener);
}
}
};
final private Adapter resourceSetChangeListener = new AdapterImpl() {
public void notifyChanged(Notification notif) {
if (Notification.ADD == notif.getEventType()) {
Resource res = (Resource) notif.getNewValue();
res.eAdapters().add(resourceLoadListener);
} else if (Notification.REMOVING_ADAPTER == notif.getEventType() && notif.getOldValue() instanceof Resource) {
System.err.println("*********" + notif);
Resource res = (Resource) notif.getOldValue();
res.eAdapters().remove(resourceLoadListener);
} else {
fireInfo("ResourceSet event " + notif.getEventType() + ": " + notif.getNewValue());
}
}
};
void setResourceSet(ResourceSet rs) {
if (null != _resourceSet) {
if (_resourceSet.equals(rs)) {
return;
}
throw new IllegalStateException("ResourceSet is already set - call clearResourceSet() first.");
}
_resourceSet = rs;
// Need to use a new ExtendedMetaData instance to avoid cached ePackage instances.
//
SERIALIZATION_OPTIONS.put(XMLResource.OPTION_EXTENDED_META_DATA, new BasicExtendedMetaData(_resourceSet.getPackageRegistry()));
_resourceSet.getLoadOptions().putAll(SERIALIZATION_OPTIONS);
registerFactory("qvt", TEFKAT_RESOURCE_FACTORY);
registerFactory("xsd", XSD_RESOURCE_FACTORY);
registerFactory("wsdl", XSD_RESOURCE_FACTORY);
registerFactory("xmi", XMI_RESOURCE_FACTORY);
registerFactory("tefkat", XMI_RESOURCE_FACTORY);
registerFactory("ecore", ECORE_RESOURCE_FACTORY);
registerFactory("xml", XML_RESOURCE_FACTORY);
_resourceSet.eAdapters().add(resourceSetChangeListener);
}
public ResourceSet getResourceSet() {
if (null == _resourceSet) {
setResourceSet(new ResourceSetImpl());
}
return _resourceSet;
}
public void clearResourceSet() {
if (null != _resourceSet) {
_resourceSet.eAdapters().remove(resourceSetChangeListener);
_resourceSet = null;
}
}
public Tefkat() {
}
@Deprecated
public boolean isIncremental() {
return isIncremental;
}
@Deprecated
public void setIncremental(boolean isIncremental) {
throw new UnsupportedOperationException("non-incremental model is deprecated");
// this.isIncremental = isIncremental;
// if (null != ruleEvaluator) {
// ruleEvaluator.INCREMENTAL = isIncremental;
// }
}
public boolean isPrintingStats() {
return printingStats;
}
public void setPrintingStats(boolean printingStats) {
this.printingStats = printingStats;
}
public void addFunction(String name, Function function) {
functions.put(name, function);
}
public void addTefkatListener(TefkatListener listener) {
if (!engineListeners.contains(listener)) {
engineListeners.add(listener);
}
}
public void removeTefkatListener(TefkatListener listener) {
engineListeners.remove(listener);
}
public boolean getInterrupted() {
return null != ruleEvaluator && ruleEvaluator.getInterrupted();
}
public void setInterrupted(boolean state) {
fireWarning("Transformation interrupted");
if (null != ruleEvaluator) {
ruleEvaluator.setInterrupted(state);
}
for (Iterator itr = threads.iterator(); itr.hasNext(); ) {
Thread thread = (Thread) itr.next();
thread.interrupt();
}
}
public boolean getRunning() {
return isRunning;
}
private void setRunning(boolean state) {
isRunning = state;
}
public void registerFactory(String ext, Resource.Factory factory) {
Map map = Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap();
map.put(ext, factory);
}
public Resource createTempResource(String prefix, String suffix) {
String filename = prefix + suffix;
// filename = File.createTempFile(prefix, suffix).getAbsolutePath();
URI tmpURI = URI.createFileURI(filename);
return getResourceSet().createResource(tmpURI);
}
public void transform(Resource transformation, Resource src, Resource tgt)
throws TefkatException {
Resource[] srcs = { src };
Resource[] tgts = { tgt };
transform(transformation, srcs, tgts);
}
public void transform(Resource transformation, Resource src, Resource tgt,
Resource tracking) throws TefkatException {
Resource[] srcs = { src };
Resource[] tgts = { tgt };
transform(transformation, srcs, tgts, tracking);
}
public void transform(Resource transformation, Resource[] srcs, Resource[] tgts)
throws TefkatException {
transform(transformation, srcs, tgts, null);
}
public void transform(Resource transformation, Resource[] srcs, Resource[] tgts,
Resource tracking) throws TefkatException {
transform(transformation, srcs, tgts, tracking, false);
}
public void transform(Resource transformation, Resource[] srcs, Resource[] tgts,
Resource tracking, boolean force) throws TefkatException {
transform(transformation, null, srcs, tgts, tracking, force);
}
public void transform(Resource transformation, Map parameters, Resource[] srcs, Resource[] tgts,
Resource tracking, boolean force) throws TefkatException {
setResourceSet(transformation.getResourceSet());
final ContainerExtent[] srcEs = new ContainerExtent[srcs.length];
final ContainerExtent[] tgtEs = new ContainerExtent[tgts.length];
final ContainerExtent trackingE = TefkatFactory.eINSTANCE.createContainerExtent();
for (int i = 0; i < srcs.length; i++) {
srcEs[i] = TefkatFactory.eINSTANCE.createContainerExtent();
srcEs[i].setResource(srcs[i]);
}
for (int i = 0; i < tgts.length; i++) {
tgtEs[i] = TefkatFactory.eINSTANCE.createContainerExtent();
tgtEs[i].setResource(tgts[i]);
}
if (null == tracking) {
trackingE.setResource(createTempResource("tefkat-tracking", ".xmi"));
} else {
trackingE.setResource(tracking);
}
transform(transformation, parameters, srcEs, tgtEs, trackingE, force);
}
public void query(Resource query, Map parameters, Extent[] srcs) throws TefkatException {
setResourceSet(query.getResourceSet());
List contents = query.getContents();
for (int j = 0; j < contents.size(); j++) {
if (contents.get(j) instanceof Query) {
Query q = (Query) contents.get(j);
Binding context = setupQueryEnvironment(parameters, srcs, q);
final long startTime = System.currentTimeMillis();
final Collection answers = evaluateQuery(context, q);
for (Object b: answers) {
System.out.println(b);
}
final long endTime = System.currentTimeMillis();
if (printingStats) {
fireInfo(DynamicObject.counter + " Dynamic Objects");
fireInfo(Tree.counter + " Trees");
fireInfo(Node.counter + " Nodes");
fireInfo(Binding.counter + " Bindings");
fireInfo("Binding/Node Ratio: " + Binding.counter / (float) Node.counter);
timings("Source", ruleEvaluator.srcResolver);
timings("Target", ruleEvaluator.tgtResolver);
for (int i = 0; i < ruleEvaluator.tgtResolver.elapsed.length; i++) {
fireInfo("TrackingUse breakdown: " + i + " " + ruleEvaluator.tgtResolver.elapsed[i]);
}
fireInfo("Query time: " + (endTime - startTime) / 1000.0 + "s");
}
// fireQueryFinished();
}
}
}
public Collection evaluateQuery(Binding context, Query q) throws ResolutionException, TefkatException {
Tree.counter = 0;
Node.counter = 0;
Binding.counter = 0;
DynamicObject.counter = 0;
// fireQueryStarted(q, srcs, context);
createRuleEvaluator(null, q, context);
if (paused) {
ruleEvaluator.pause();
}
final Collection answers = ruleEvaluator.runQuery(q);
return answers;
}
private Binding setupQueryEnvironment(Map parameters, Extent[] srcs, Query q) throws ResolutionException {
Binding context = new Binding();
List extentVars = q.getVars();
for (final Iterator itr = extentVars.iterator(); itr.hasNext(); ) {
final Var var = (Var) itr.next();
final String varName = var.getName();
if (parameters.containsKey(varName)) {
context.add(var, parameters.get(varName));
}
}
int idx = 0;
for (int k = 0; k < srcs.length; k++) {
Var var;
do {
if (idx >= extentVars.size()) {
throw new ResolutionException(null, "Too many parameters while processing " + srcs[k] + ". Expected " + extentVars.size() + ", got approximately " + (parameters.size() + srcs.length));
}
var = (Var) extentVars.get(idx++);
} while (context.lookup(var) != null);
context.add(var, srcs[k]);
}
return context;
}
void transform(Resource transformation, Map parameters, Extent[] srcs, Extent[] tgts,
Extent trackingExtent, boolean force) throws TefkatException {
setResourceSet(transformation.getResourceSet());
try {
fireStart();
List contents = transformation.getContents();
for (int j = 0; j < contents.size(); j++) {
if (contents.get(j) instanceof Transformation) {
Transformation t = (Transformation) contents.get(j);
Binding context = new Binding();
List extentVars = t.getVars();
for (final Iterator itr = extentVars.iterator(); itr.hasNext(); ) {
final Var var = (Var) itr.next();
final String varName = var.getName();
if (parameters.containsKey(varName)) {
context.add(var, parameters.get(varName));
}
}
int idx = 0;
for (int k = 0; k < srcs.length; k++) {
Var var;
do {
if (idx >= extentVars.size()) {
throw new ResolutionException(null, "Too many parameters while processing " + srcs[k] + ". Expected " + extentVars.size() + ", got approximately " + (parameters.size() + srcs.length + tgts.length));
}
var = (Var) extentVars.get(idx++);
} while (context.lookup(var) != null);
context.add(var, srcs[k]);
}
for (int k = 0; k < tgts.length; k++) {
Var var;
do {
if (idx >= extentVars.size()) {
throw new ResolutionException(null, "Too many parameters found while processing " + srcs[k] + ". Expected " + extentVars.size() + ", got approximately " + (parameters.size() + srcs.length + tgts.length));
}
var = (Var) extentVars.get(idx++);
} while (context.lookup(var) != null);
context.add(var, tgts[k]);
}
Tree.counter = 0;
Node.counter = 0;
Binding.counter = 0;
DynamicObject.counter = 0;
fireTransformationStarted(t, srcs, tgts, trackingExtent, context);
createRuleEvaluator(trackingExtent, t, context);
if (paused) {
ruleEvaluator.pause();
}
long startTime = System.currentTimeMillis();
ruleEvaluator.runTransformation(t, force);
long endTime = System.currentTimeMillis();
if (printingStats) {
fireInfo(DynamicObject.counter + " Dynamic Objects");
fireInfo(Tree.counter + " Trees");
fireInfo(Node.counter + " Nodes");
fireInfo(Binding.counter + " Bindings");
fireInfo("Binding/Node Ratio: " + Binding.counter / (float) Node.counter);
timings("Source", ruleEvaluator.srcResolver);
timings("Target", ruleEvaluator.tgtResolver);
for (int i = 0; i < ruleEvaluator.tgtResolver.elapsed.length; i++) {
fireInfo("TrackingUse breakdown: " + i + " " + ruleEvaluator.tgtResolver.elapsed[i]);
}
// fireInfo("TrackingUse breakdown: " +
// ruleEvaluator.tgtResolver.counter + "\t" +
// ruleEvaluator.tgtResolver.elapsed[0] + "\t" +
// ruleEvaluator.tgtResolver.elapsed[1] + "\t" +
// ruleEvaluator.tgtResolver.elapsed[2] + "\t" +
// ruleEvaluator.tgtResolver.elapsed[3]
// );
fireInfo("Transformation time: " + (endTime - startTime) / 1000.0 + "s");
}
fireTransformationFinished();
}
}
} finally {
fireStop();
}
}
private void timings(String label, AbstractResolver resolver) {
fireInfo("");
fireInfo(" " + label + " Term\tCalls\tTime\tAvg (ms)");
fireInfo(" ---------------------------------------");
for (Iterator itr = resolver.elapsedTime.entries().iterator(); itr.hasNext(); ) {
IntMap.Entry entry = (IntMap.Entry) itr.next();
if (null != entry) {
EClass cls = (EClass) entry.key;
int count = resolver.callCount.get(cls);
fireInfo(" " + cls.getName() + "\t" + count + "\t" + entry.value + "\t" + entry.value/(float)count);
}
}
}
/**
* @param trackingExtent
* @param scope
* @param context
* @throws ResolutionException
*/
private void createRuleEvaluator(Extent trackingExtent, PatternScope scope, Binding context) throws ResolutionException {
// Get all the transitively referenced Resources
final Map nameMap = new HashMap();
buildPackageNameMap(scope, nameMap);
// try {
// ModelUtils.resolveTrackingClassNames(t, nameMap);
// } catch (TefkatException e) {
// throw new ResolutionException(null, "Could not resolve tracking class references", e);
// }
ruleEvaluator = new RuleEvaluator(context, trackingExtent, nameMap, engineListeners);
ruleEvaluator.setInterrupted(false);
// ruleEvaluator.INCREMENTAL = isIncremental;
Evaluator evaluator = ruleEvaluator.getEvaluator();
for (final Iterator itr = functions.entrySet().iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
String name = (String) entry.getKey();
Function function = (Function) entry.getValue();
evaluator.addFunction(name, function);
}
}
private void buildPackageNameMap(PatternScope scope, Map nameMap) throws ResolutionException {
final Map<String, Set<EPackage>> importedNamespaces = new HashMap<String, Set<EPackage>>();
importedNamespaces.put(null, new HashSet<EPackage>());
final EPackage.Registry registry = getResourceSet().getPackageRegistry();
for (final Iterator itr = scope.getNamespaceDeclarations().iterator(); itr.hasNext(); ) {
final NamespaceDeclaration nsd = (NamespaceDeclaration) itr.next();
final String name = nsd.getPrefix();
final String uriStr = nsd.getURI();
Set<EPackage> packages = importedNamespaces.get(name);
if (null == packages) {
packages = new HashSet<EPackage>();
importedNamespaces.put(name, packages);
}
importPackage(packages, registry, uriStr);
}
final Set<EPackage> nullPackages = importedNamespaces.get(null);
if (null != scope.eResource()) {
importPackage(nullPackages, registry, scope.eResource().getURI().toString());
}
for (final Iterator itr = scope.getImportedPackages().iterator(); itr.hasNext(); ) {
final String uriStr = (String) itr.next();
importPackage(nullPackages, registry, uriStr);
}
for (final Iterator itr = importedNamespaces.entrySet().iterator(); itr.hasNext(); ) {
final Map.Entry entry = (Entry) itr.next();
final String name = (String) entry.getKey();
final Set packages = (Set) entry.getValue();
ModelUtils.buildPackageNameMaps(packages, nameMap, name);
}
}
private void importPackage(Set<EPackage> packages, EPackage.Registry registry, String uriStr) {
final EPackage pkg = registry.getEPackage(uriStr);
if (null != pkg) {
packages.add(pkg);
} else {
final Resource res = getResourceSet().getResource(URI.createURI(uriStr), true);
if (null == res) {
fireWarning("Unable to load model for URI: " + uriStr);
return;
}
if (false) { // strict checking
boolean found = false;
for (Object o: res.getContents()) {
if (o instanceof EPackage) {
EPackage p = (EPackage) o;
if (uriStr.equals(p.getNsURI())) {
packages.add(p);
// registry.put(uriStr, p);
found = true;
break;
}
}
}
if (!found) {
fireWarning("Unable to find EPackage with NsURI: " + uriStr);
}
} else {
for (Object o: res.getContents()) {
if (o instanceof EPackage) {
EPackage p = (EPackage) o;
packages.add(p);
}
}
}
}
}
// private void buildNameMap(Transformation t, Map nameMap) throws ResolutionException {
// Map importedNamespaces = new HashMap();
// importedNamespaces.put(null, new HashSet());
//
// EPackage.Registry registry = getResourceSet().getPackageRegistry();
//
// for (final Iterator itr = t.getNamespaceDeclarations().iterator(); itr.hasNext(); ) {
// NamespaceDeclaration nsd = (NamespaceDeclaration) itr.next();
// String name = nsd.getPrefix();
// String uriStr = nsd.getURI();
// Set resources = (Set) importedNamespaces.get(name);
// if (null == resources) {
// resources = new HashSet();
// importedNamespaces.put(name, resources);
// }
// importResource(resources, registry, uriStr);
// }
// Set resources = (Set) importedNamespaces.get(null);
// resources.add(t.eResource());
// for (final Iterator itr = t.getImportedPackages().iterator(); itr.hasNext(); ) {
// String uriStr = (String) itr.next();
// importResource(resources, registry, uriStr);
// }
//
// for (final Iterator itr = importedNamespaces.entrySet().iterator(); itr.hasNext(); ) {
// Map.Entry entry = (Entry) itr.next();
// String name = (String) entry.getKey();
// resources = findAllResources((Collection) entry.getValue());
// ModelUtils.buildNameMaps(resources, nameMap, name);
// }
// }
// private void importResource(Set resources, EPackage.Registry registry, String uriStr) throws ResolutionException {
// // Avoid explicitly loading resources corresponding to packages that
// // have already been loaded (or dynamically created!)
// //
// try {
// if (registry.containsKey(uriStr)) {
// resources.add(registry.getEPackage(uriStr).eResource());
// } else {
// // gracefully handle the case where an XSD has no targetNamespace
// // (there can be only one :-)
// EPackage nullPkg = registry.getEPackage(null);
// if (null != nullPkg && uriStr.equals(nullPkg.getNsURI())) {
// resources.add(nullPkg.eResource());
// } else {
// resources.add(getResource(uriStr));
// }
// }
// } catch (IOException e) {
// throw new ResolutionException(null, "Could not import model: " + uriStr, e);
// }
// }
// Attempting to use a separate thread to allow hung resource loads to be interrupted
private Resource getResource(final String location) throws IOException {
final Resource[] res = { null };
final Exception[] error = { null };
Thread thread = new Thread() {
public void run() {
try {
URI uri = URI.createURI(location);
res[0] = getResourceSet().getResource(uri, true);
} catch (Exception e) {
error[0] = e;
} finally {
threads.remove(this);
}
}
};
threads.add(thread);
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
res[0] = null;
error[0] = e;
}
if (null == res[0] || null != error[0]) {
IOException e = new IOException("Failed to load Resource from " + location);
if (null != error[0]) {
e.initCause(error[0]);
}
throw e;
} else if (null != res[0]) {
List errors = res[0].getErrors();
if (errors.size() > 0) {
throw new IOException("Parse errors: " + errors);
}
}
return res[0];
}
private Resource createResource(String location) {
URI uri = URI.createURI(location);
Resource res = getResourceSet().createResource(uri);
return res;
}
/**
* Takes a TefkatConfig.TransformationTask and performs the described
* transformation.
*
* @throws IOException
* @throws TefkatException
*/
public void transform(TransformationTask task, boolean save, boolean force)
throws IOException, TefkatException {
try {
// String classpathList = (String) task.getProperties().get("classpaths");
// ClassLoader loader;
// if (null != classpathList) {
// String[] classpaths = classpathList.split("\\s*,\\s*");
// URL[] urls = new URL[classpaths.length];
// for (int i = 0; i < classpaths.length; i++) {
// urls[i] = new URL(classpaths[i]);
// System.err.println("[" + urls[i] + "]");
// }
// loader = new URLClassLoader(urls, this.getClass().getClassLoader());
// } else {
// loader = this.getClass().getClassLoader();
// }
// String packageList = (String) task.getProperties().get("packages");
// if (null != packageList) {
// String[] packages = packageList.split("\\s*,\\s*");
// for (int i = 0; i < packages.length; i++) {
// System.err.println("<" + packages[i] + ">");
// Class c;
// c = loader.loadClass(packages[i]);
// //c = Class.forName(packages[i]);
// System.err.println(".eINSTANCE = " + c.getField("eINSTANCE").get(null));
// }
// }
if (null != task.eResource()) {
setResourceSet(task.eResource().getResourceSet());
}
List uriMaps = task.getUriMap();
String incremental = (String) task.getProperties().get("incremental");
if (null != incremental) {
setIncremental(Boolean.valueOf(incremental).booleanValue());
}
String statistics = (String) task.getProperties().get("statistics");
if (null != statistics) {
setPrintingStats(Boolean.valueOf(statistics).booleanValue());
}
Resource transformationR = null;
Map parameters = new HashMap();
Resource[] sourcesR;
Resource[] targetsR;
Resource traceR = null;
URIConverter converter = getResourceSet().getURIConverter();
Map URIMap = converter.getURIMap();
for (Iterator itr = uriMaps.iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
URI uri1 = URI.createURI((String) entry.getKey());
URI uri2 = URI.createURI((String) entry.getValue());
URIMap.put(uri1, uri2);
}
transformationR = getResource(task.getTransformation().getLocationUri());
List sources = task.getSourceModels();
// sourcesR = new Resource[sources.size()];
List sourcesL = new ArrayList();
for (int i = 0; i < sources.size(); i++) {
final Model model = (Model) sources.get(i);
final Resource resource = getResource((model).getLocationUri());
final String varGroup = model.getVarGroup();
// handle various guises of an un-specified varGroup
if (varGroup != null && varGroup.trim().length() > 0) {
ReferenceExtent extent;
if (parameters.containsKey(varGroup)) {
extent = (ReferenceExtent) parameters.get(varGroup);
} else {
extent = TefkatFactory.eINSTANCE.createReferenceExtent();
parameters.put(varGroup, extent);
}
extent.getResources().add(resource);
} else {
sourcesL.add(resource);
}
}
sourcesR = (Resource[]) sourcesL.toArray(new Resource[sourcesL.size()]);
List targets = task.getTargetModels();
targetsR = new Resource[targets.size()];
if (ExecutionMode.REPLACE_LITERAL.equals(task.getMode())) {
for (int i = 0; i < targetsR.length; i++) {
targetsR[i] = createResource(((Model) targets.get(i)).getLocationUri());
}
if (null != task.getTrace()) {
traceR = createResource(task.getTrace().getLocationUri());
}
} else {
for (int i = 0; i < targetsR.length; i++) {
targetsR[i] = getResource(((Model) targets.get(i)).getLocationUri());
}
if (null != task.getTrace()) {
traceR = getResource(task.getTrace().getLocationUri());
throw new UnsupportedOperationException("Not yet implemented: need to initialise internal structures wrt loaded trace model");
}
}
transform(transformationR, parameters, sourcesR, targetsR, traceR, force);
for (int i = 0; i < targetsR.length; i++) {
setObjectIds(targetsR[i]);
removeContainedObjectsFromResourceContents(targetsR[i]);
if (save) {
targetsR[i].save(SERIALIZATION_OPTIONS);
}
}
if (null != traceR) {
setObjectIds(traceR);
if (save) {
traceR.save(SERIALIZATION_OPTIONS);
}
}
// } catch (ClassNotFoundException e) {
// throw new ResolutionException(null, "Could not find requested model classes", e);
// } catch (IllegalArgumentException e) {
// throw new ResolutionException(null, "Could not initialise requested model classes", e);
// } catch (SecurityException e) {
// throw new ResolutionException(null, "Could not initialise requested model classes", e);
// } catch (IllegalAccessException e) {
// throw new ResolutionException(null, "Could not initialise requested model classes", e);
// } catch (NoSuchFieldException e) {
// throw new ResolutionException(null, "Could not initialise requested model classes", e);
} finally {
// clear out loaded resources so that a reload is forced
// next time through - things may have changed so we don't
// want any cached state.
//
clearResourceSet();
}
}
private void removeContainedObjectsFromResourceContents(Resource resource) {
HashSet<EObject> toRemove = new HashSet<EObject>();
for (EObject eobj : resource.getContents()) {
if (null != eobj.eContainer()) {
//resource.getContents().remove(eobj);
//No concurrent collection removal!
toRemove.add(eobj);
}
}
resource.getContents().removeAll(toRemove);
}
/**
* Sets the XMI IDs of the objects and avoids duplicates in the XMIResource
* @param res
*/
private static void setObjectIds(Resource res) {
if (res instanceof XMIResource) {
XMIResource xres = (XMIResource) res;
Object[] roots = xres.getContents().toArray();
for (int i = roots.length - 1; i >= 0; i--) {
EObject obj = (EObject) roots[i];
fixObjectId(xres, obj);
}
}
}
private static void fixObjectId(XMIResource xres, EObject obj) {
// Set XMI ID if not already set
if (null == xres.getID(obj)) {
xres.setID(obj, String.valueOf(obj.hashCode()));
}
// remove direct containment for things that are transitively contained
/* Moved into removeContainedObjectsFromResourceContents()
if (null != obj.eContainer()) {
xres.getContents().remove(obj);
}
*/
Object[] children = obj.eContents().toArray();
for (int i = children.length - 1; i >= 0; i--) {
fixObjectId(xres, (EObject) children[i]);
}
}
public void pause() {
paused = true;
if (null != ruleEvaluator) {
ruleEvaluator.pause();
}
}
public void step() {
ruleEvaluator.step();
}
public void stepReturn() {
ruleEvaluator.stepReturn();
}
public void resume() {
paused = false;
if (null != ruleEvaluator) {
ruleEvaluator.resume();
}
}
private void fireResourceLoaded(Resource res) {
for (Iterator itr = engineListeners.iterator(); itr.hasNext();) {
try {
((TefkatListener) itr.next()).resourceLoaded(res);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
protected void fireInfo(String message) {
for (Iterator itr = engineListeners.iterator(); itr.hasNext(); ) {
try {
((TefkatListener) itr.next()).info(message);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
protected void fireWarning(String message) {
for (Iterator itr = engineListeners.iterator(); itr.hasNext(); ) {
try {
((TefkatListener) itr.next()).warning(message);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private void fireStart() {
setRunning(true);
for (Iterator itr = engineListeners.iterator(); itr.hasNext();) {
try {
((TefkatListener) itr.next()).started();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private void fireStop() {
setRunning(false);
for (Iterator itr = engineListeners.iterator(); itr.hasNext();) {
try {
((TefkatListener) itr.next()).stopped();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private void fireTransformationStarted(Transformation transformation, Extent[] srcs, Extent[] tgts, Extent trace,
Binding context) {
for (Iterator itr = engineListeners.iterator(); itr.hasNext();) {
try {
((TefkatListener) itr.next()).transformationStarted(transformation, srcs, tgts, trace, context);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private void fireTransformationFinished() {
for (Iterator itr = engineListeners.iterator(); itr.hasNext();) {
try {
((TefkatListener) itr.next()).transformationFinished();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
/**
* Given a list of Resources, transitively load all resources that contain referenced stuff.
*
* @param resources
* @return
*/
static private final Set findAllResources(Collection resources) {
Set result = new HashSet(resources);
while (resources.size() > 0) {
Set newResources = new HashSet();
System.err.println("warning, skipping load of referenced resources");
for (Iterator itr = resources.iterator(); false && itr.hasNext(); ) {
Resource res = (Resource) itr.next();
System.err.println("findAllResources: " + res);
Map refs = EcoreUtil.ExternalCrossReferencer.find(res);
for (Iterator refItr = refs.keySet().iterator(); refItr.hasNext(); ) {
EObject o = (EObject) refItr.next();
Resource newRes = o.eResource();
// ignore things we've already seen
if (newRes != null && !result.contains(newRes)) {
newResources.add(newRes);
// fireResourceLoaded(newRes);
}
}
}
// newResources.removeAll(result); // ignore things we've already seen
result.addAll(newResources); // remember everything for result
resources = newResources; // get ready to iterate over the new things
}
return result;
}
public void addParserListener(final ParserListener listener) {
TEFKAT_RESOURCE_FACTORY.addParserListener(listener);
}
public void removeParserListener(final ParserListener listener) {
TEFKAT_RESOURCE_FACTORY.removeParserListener(listener);
}
}