Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfjouault2015-01-05 11:39:33 -0500
committerfjouault2015-01-05 11:39:33 -0500
commit3b2752183f58f2fe10151e138be7a805acc7cb4a (patch)
tree48b7e528a9c44f24799e5417b8a40a8dc7780163
parentd7b82d9f79eeb03bfc3502b52335ee39b57076dd (diff)
downloadorg.eclipse.atl.tcs-3b2752183f58f2fe10151e138be7a805acc7cb4a.tar.gz
org.eclipse.atl.tcs-3b2752183f58f2fe10151e138be7a805acc7cb4a.tar.xz
org.eclipse.atl.tcs-3b2752183f58f2fe10151e138be7a805acc7cb4a.zip
moved inject and extract methods into new class AbstractLanguage
AbstractLanguage may be reused by other implementations of Language so that they do not need to reimplement inject and extract.
-rw-r--r--plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/AbstractLanguage.java405
-rw-r--r--plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/adhoc/WorkspaceLanguage.java321
2 files changed, 476 insertions, 250 deletions
diff --git a/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/AbstractLanguage.java b/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/AbstractLanguage.java
new file mode 100644
index 0000000..e89178f
--- /dev/null
+++ b/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/AbstractLanguage.java
@@ -0,0 +1,405 @@
+/**
+ * Copyright (c) 2015 ESEO.
+ * 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:
+ * ESEO - initial API and implementation
+ *
+ * $Id$
+ */
+package org.eclipse.gmt.tcs.metadata;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gmt.tcs.extractor.ModelAdapter;
+import org.eclipse.gmt.tcs.extractor.TCSExtractor;
+import org.eclipse.gmt.tcs.injector.ASMModelAdapter;
+import org.eclipse.gmt.tcs.injector.ElementTrace;
+import org.eclipse.gmt.tcs.metadata.adhoc.TCSInjection;
+import org.eclipse.gmt.tcs.metadata.adhoc.VirtualExtractorModelAdapter;
+import org.eclipse.gmt.tcs.metadata.adhoc.VirtualModelAdapter;
+import org.eclipse.m2m.atl.core.IModel;
+import org.eclipse.m2m.atl.core.IReferenceModel;
+import org.eclipse.m2m.atl.core.emf.EMFInjector;
+import org.eclipse.m2m.atl.core.emf.EMFModelFactory;
+import org.eclipse.m2m.atl.core.launch.ILauncher;
+import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel;
+import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModelElement;
+import org.eclipse.m2m.atl.drivers.emf4atl.EMFModelLoader;
+import org.eclipse.m2m.atl.dsls.DSLResourceProvider;
+import org.eclipse.m2m.atl.dsls.tcs.injector.CompletionInformation;
+import org.eclipse.m2m.atl.dsls.textsource.TextSource;
+import org.eclipse.m2m.atl.engine.emfvm.StackFrame;
+import org.eclipse.m2m.atl.engine.emfvm.VMException;
+import org.eclipse.m2m.atl.engine.emfvm.launch.EMFVMLauncher;
+import org.eclipse.m2m.atl.engine.emfvm.lib.AbstractStackFrame;
+import org.eclipse.m2m.atl.engine.emfvm.lib.ExecEnv;
+import org.eclipse.m2m.atl.engine.emfvm.lib.LibExtension;
+import org.eclipse.m2m.atl.engine.emfvm.lib.Operation;
+import org.eclipse.m2m.atl.engine.emfvm.lib.Tuple;
+import org.eclipse.m2m.atl.engine.vm.AtlModelHandler;
+import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;
+
+/**
+ * This Language implements generic inject and extract methods by relying abstract methods to access
+ * required resources.
+ * A concrete subclass must implement these abstract methods in addition to all missing methods from
+ * Language, but can rely on the generic inject and extract methos.
+ *
+ * @author Frédéric Jouault
+ */
+public abstract class AbstractLanguage implements Language {
+ public Object inject(ModelFactory factory, Object model, TextSource source, final Map params) {
+ try {
+ params.put("name", this.getName());
+ // TODO: support multiple parserGenerators
+ //params.put("parserGenerator", getParserGenerator()); // not specifying any parserGenerator will default to antlr3
+
+ Object metamodel = getMetamodel(factory);
+
+ // Grab a reference to problemModel now, because if we get it after the injection,
+ // it may have been replaced by a model adapter.
+ Object problemModel = params.get("problems");
+
+ if(model == null) {
+ model = factory.newModel("model.xmi", metamodel);
+ }
+ final Object model_ = model;
+
+ final Map hyperlinks = (Map)params.get("hyperlinks");
+ final Map locations = (Map)params.get("locationByElement");
+ Map trace_ = (Map)params.get("trace");
+ if((hyperlinks != null) && (trace_ == null)) {
+ trace_ = new HashMap();
+ params.put("trace", trace_);
+ }
+ final Map trace = trace_;
+
+ final VirtualModelAdapter vma = new VirtualModelAdapter(new ASMModelAdapter(model));
+ params.put("modelAdapter", vma);
+
+ Object ret = TCSInjection.inject(factory, model, metamodel, source, params, this.getJarURL());
+
+ final ExecEnv execEnv_[] = new ExecEnv[1];
+ if(problemModel != null) {
+
+ // TODO: only if no parsing error?
+ VMLauncher vmLauncher = (VMLauncher)params.get("vmLauncher");
+ if(vmLauncher != null) {
+ if(this.hasWFR()) {
+ /*
+ Map libraries = new HashMap();
+ libraries.put("TCSVirtualProperties", vma.getLibrary(name));
+ String libNameAndPathsCSV = getProperty("wfr.libraries");
+ if(libNameAndPathsCSV != null) {
+ String libNameAndPaths[] = libNameAndPathsCSV.split(",");
+ for(int i = 0 ; i < libNameAndPaths.length ; i++) {
+ String parts[] = libNameAndPaths[i].split("=");
+ libraries.put(parts[0], project.getFile(parts[1]).getLocationURI().toURL());
+ }
+ }
+ Map models = new HashMap();
+ models.put(name, metamodel);
+ models.put("IN", ret);
+ models.put("Problem", factory.metamodelOf(problemModel));
+ models.put("OUT", problemModel);
+ vmLauncher.launch(wfrFile.getLocationURI().toURL(), models, libraries);
+ */
+ // override VM Launcher to use EMFVM
+ ILauncher launcher = new EMFVMLauncher();
+ launcher.initialize(Collections.emptyMap());
+
+ EMFModelFactory emfFac = new EMFModelFactory();
+
+ IReferenceModel pbMM = emfFac.newReferenceModel();
+ new EMFInjector().inject(pbMM, ((ASMEMFModel)factory.metamodelOf(problemModel)).getExtent());
+
+ IReferenceModel mm = emfFac.newReferenceModel();
+ new EMFInjector().inject(mm, ((ASMEMFModel)factory.metamodelOf(model)).getExtent());
+
+ IModel m = emfFac.newModel(mm);
+ new EMFInjector().inject(m, ((ASMEMFModel)model).getExtent());
+
+ IModel pbM = emfFac.newModel(pbMM);
+ new EMFInjector().inject(pbM, ((ASMEMFModel)problemModel).getExtent());
+
+ launcher.addInModel(mm, this.getName(), "MOF");
+ launcher.addInModel(m, "IN", this.getName());
+ launcher.addInModel(pbMM, "Problem", "MOF");
+ launcher.addOutModel(pbM, "OUT", "Problem");
+
+ try {
+ this.addWFRLibraries(launcher);
+
+ Map options = new HashMap();
+ List extensionObjects = new ArrayList();
+ extensionObjects.add(new LibExtension() {
+ public void apply(ExecEnv execEnv, Map options) {
+ execEnv_[0] = execEnv;
+ // allVirtualProperties global/context-less helper => not possible here because ASMModule
+ // only created after extensions are called.
+ // Workaround: register on String (for no specific reason (could be any other type)).
+ final Set allProperties = vma.getAllProperties();
+
+ // We keep document order. Until GenericResolver can topologically sort, we must make sure to return in the same order.
+ // Actually, it should be metamodel order (closer to external resolver with specific metamodel), but document order is even better
+ // (closer to internal resolver, and therefore same best practices, such as only looking in a reference resolved before, apply).
+ execEnv.registerOperation(String.class, new Operation(1, "allVirtualProperties") {
+ public Object exec(AbstractStackFrame frame) {
+ return allProperties;
+ }
+ });
+
+ final CompletionInformation ci = (CompletionInformation)params.get("completionInformation");
+ execEnv.registerOperation(String.class, new Operation(1, "offsetToComplete") {
+ public Object exec(AbstractStackFrame frame) {
+ if(ci != null) {
+ return Integer.valueOf(ci.getOffset());
+ } else {
+ return null;
+ }
+ }
+ });
+
+ if(params.containsKey("hyperlinks")) {
+ execEnv.registerOperation(String.class, new Operation(4, "addHyperlink") {
+ public Object exec(AbstractStackFrame frame) {
+ Object locals[] = frame.getLocalVars();
+ // TODO: generalize this
+ Object source = ((ASMEMFModel)model_).getASMModelElement((EObject)locals[1]);
+ Object target = ((ASMEMFModel)model_).getASMModelElement((EObject)locals[3]);
+ hyperlinks.put(
+ ((ElementTrace)trace.get(source)).getPropertyLocation((String)locals[2]),
+ locations.get(target)
+ );
+ return null;
+ }
+ });
+ }
+
+ // register weaving helpers used to represent virtual properties
+ for(Iterator i = allProperties.iterator() ; i.hasNext() ; ) {
+ Tuple t = (Tuple)i.next();
+ Object type = t.get(null, "eContainingClass");
+ String name = (String)t.get(null, "name");
+ execEnv.registerWeavingHelper(type, name, null);
+ }
+
+ // store values
+ for(Iterator i = vma.getVirtualProperties().entrySet().iterator() ; i.hasNext() ; ) {
+ Map.Entry ei = (Map.Entry)i.next();
+ Object element = ei.getKey();
+ if(element instanceof ASMEMFModelElement) {
+ element = ((ASMEMFModelElement)element).getObject();
+ }
+ // <String, Object>
+ Map slots = (Map)ei.getValue();
+ for(Iterator j = slots.entrySet().iterator() ; j.hasNext() ; ) {
+ Map.Entry ej = (Map.Entry)j.next();
+ String propertyName = (String)ej.getKey();
+ Object value = ej.getValue();
+ execEnv.setHelperValue(element, propertyName, value);
+ }
+ }
+ }
+ });
+
+ options.put("extensionObjects", extensionObjects);
+ launcher.launch(ILauncher.RUN_MODE, null, options, new Object[] {this.getWFR()});
+ } catch(IOException ioe) {
+ throw new RuntimeException("could not run WFR transformation", ioe);
+ } catch(VMException vme) {
+ vme.printStackTrace();
+ }
+ }
+ }
+ }
+ CompletionInformation ci = (CompletionInformation)params.get("completionInformation");
+ if(ci != null) {
+ if((ci.getProposals().size() == 1) && (ci.getProposals().get(0) instanceof Object[])) {
+ // deal with external resolver information here
+ Object args[] = (Object[])ci.getProposals().get(0);
+ ci.getProposals().clear();
+
+ if(execEnv_[0] != null) {
+ EObject ame = ((ASMEMFModelElement)args[0]).getObject();
+ String propertyName = (String)args[1];
+ String prefix = (String)args[2];
+
+ ExecEnv execEnv = execEnv_[0];
+ Operation op = execEnv.getOperation(ame.eClass(), "getCompletionProposals");
+ if(op != null) {
+ StackFrame stackFrame = new StackFrame(execEnv, null, op);
+ Object localVars[] = new Object[op.getMaxLocals()];
+ localVars[0] = ame;
+ localVars[1] = propertyName;
+ stackFrame.setLocalVars(localVars);
+ Object proposals = op.exec(stackFrame);
+ // if(proposals instanceof OclUndefined || ret instanceof ASMOclUndefined) {
+ // ret = null;
+ // }
+ // return ret;
+ ci.getProposals().addAll((Collection)proposals);
+ ci.setPrefix(prefix);
+ System.out.println(prefix + " " + proposals);
+ }
+ }
+ }
+ }
+ if(hyperlinks != null) {
+ // Change target to location of "name" attribute if it exists.
+
+ // TODO:
+ // - make this optional
+ // - make this generic (i.e., use refersTo information)
+ // - make it doable from transformation (need to represent ElementTraces as model)
+
+ Map newLocationFromOld = new HashMap(); // only for those that change
+ for(Iterator i = locations.entrySet().iterator() ; i.hasNext() ; ) {
+ Map.Entry entry = (Map.Entry)i.next();
+ Object element = entry.getKey();
+ ElementTrace et = (ElementTrace)trace.get(element);
+ if(et != null) {
+ Object newLocation = et.getPropertyLocation("name");
+ if(newLocation != null) {
+ Object oldLocation = entry.getValue();
+ newLocationFromOld.put(oldLocation, newLocation);
+ }
+ } else {
+ // e.g., auto-created elements
+ }
+ }
+
+ // Remarks:
+ // - after this transformation, text hovers may be incomplete if hyperlinks are used for this purpose
+ // => therefore special "ofn=" (old from new) hyperlinks are added
+ Map oldLocationFromNew = new HashMap();
+ for(Iterator i = hyperlinks.entrySet().iterator() ; i.hasNext() ; ) {
+ Map.Entry entry = (Map.Entry)i.next();
+ Object oldTarget = entry.getValue();
+ Object newTarget = newLocationFromOld.get(oldTarget);
+ if(newTarget != null) {
+ entry.setValue(newTarget);
+ oldLocationFromNew.put("ofn=" + newTarget, oldTarget);
+ }
+ }
+ hyperlinks.putAll(oldLocationFromNew);
+ }
+
+ return ret;
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("Could not inject", e);
+ }
+ }
+
+ public void extract(ModelFactory factory, Object model, OutputStream out, final Map params) {
+ this.addExtractOptions(params);
+
+ // begin PreExtract
+ if(this.hasPreExtract()) {
+ ILauncher launcher = new EMFVMLauncher();
+ launcher.initialize(Collections.emptyMap());
+
+ EMFModelFactory emfFac = new EMFModelFactory();
+
+ IReferenceModel mm = emfFac.newReferenceModel();
+ new EMFInjector().inject(mm, ((ASMEMFModel)factory.metamodelOf(model)).getExtent());
+
+ IModel m = emfFac.newModel(mm);
+ new EMFInjector().inject(m, ((ASMEMFModel)model).getExtent());
+
+ launcher.addInModel(mm, this.getName(), "MOF");
+ launcher.addInModel(m, "IN", this.getName());
+
+ try {
+ this.addPreExtractLibraries(launcher);
+
+ Map options = new HashMap();
+ List extensionObjects = new ArrayList();
+ extensionObjects.add(new LibExtension() {
+ public void apply(final ExecEnv execEnv, Map options) {
+ execEnv.registerOperation(String.class, new Operation(1, "setASMModule") {
+ public Object exec(AbstractStackFrame frame) {
+ ModelAdapter ma = (ModelAdapter)params.get("modelAdapter");
+ if(ma == null) {
+ ma = new org.eclipse.gmt.tcs.extractor.ASMModelAdapter();
+ }
+ VirtualExtractorModelAdapter vma = new VirtualExtractorModelAdapter(ma, execEnv, frame.getAsmModule());
+ params.put("modelAdapter", vma);
+
+ return frame.getLocalVars()[0];
+ }
+ });
+ }
+ });
+ options.put("extensionObjects", extensionObjects);
+ launcher.launch(ILauncher.RUN_MODE, null, options, new Object[] {this.getPreExtract()});
+ } catch(IOException ioe) {
+ throw new RuntimeException("Could not execute pre-extract transformation", ioe);
+ }
+ }
+ // end PreExtract
+
+ ASMModel format = null;
+ Object useTCSLanguage = params.get("useTCSLanguage");
+ if(useTCSLanguage != null && ((Boolean)useTCSLanguage).booleanValue()) {
+ Map oparams = new HashMap();
+ format = (ASMModel)LanguageRegistry.getDefault().getLanguage("tcs").inject(factory, format, this.getTCS(), oparams);
+ } else {
+ EMFModelLoader ml = (EMFModelLoader)AtlModelHandler.getDefault(AtlModelHandler.AMH_EMF).createModelLoader();
+ ASMModel tcsMetamodel = (ASMModel)params.get("tcsMetamodel");
+ if(tcsMetamodel == null) {
+ try {
+ tcsMetamodel = ml.loadModel("TCS", ml.getMOF(), DSLResourceProvider.getDefault().getResource("TCS/Metamodel/TCS.ecore").asEMFURI());
+ } catch(IOException ioe) {
+ throw new RuntimeException("Could not load TCS metamodel", ioe);
+ }
+ }
+ format = ml.newModel("syntax", "model.xmi", tcsMetamodel);
+ Map oparams = new HashMap();
+ oparams.put("name", "TCS");
+ URL tcsJar = (URL)params.get("tcsJar");
+ if(tcsJar == null) {
+ tcsJar = DSLResourceProvider.getDefault().getResource("TCS/Syntax/TCS-parser.jar").asURL();
+ }
+ TCSInjection.inject(factory, format, tcsMetamodel, this.getTCS(), oparams, tcsJar);
+ }
+
+ params.put("format", format);
+ new TCSExtractor().extract((ASMModel)model, out, params);
+ }
+
+ protected abstract void addWFRLibraries(ILauncher launcher) throws IOException;
+
+ protected abstract boolean hasWFR();
+
+ protected abstract InputStream getWFR() throws IOException;
+
+ protected abstract boolean hasPreExtract();
+
+ protected abstract InputStream getPreExtract() throws IOException;
+
+ protected abstract void addPreExtractLibraries(ILauncher launcher) throws IOException;
+
+ protected abstract void addExtractOptions(Map params);
+
+ protected abstract TextSource getTCS();
+
+ protected abstract URL getJarURL() throws MalformedURLException;
+}
diff --git a/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/adhoc/WorkspaceLanguage.java b/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/adhoc/WorkspaceLanguage.java
index c3a66e3..c657cd2 100644
--- a/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/adhoc/WorkspaceLanguage.java
+++ b/plugins/org.eclipse.gmt.tcs.metadata/src/org/eclipse/gmt/tcs/metadata/adhoc/WorkspaceLanguage.java
@@ -15,57 +15,31 @@ package org.eclipse.gmt.tcs.metadata.adhoc;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.net.URL;
import java.util.Map;
import java.util.Properties;
-import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.gmt.tcs.extractor.TCSExtractor;
-import org.eclipse.gmt.tcs.injector.ASMModelAdapter;
-import org.eclipse.gmt.tcs.injector.ElementTrace;
+import org.eclipse.gmt.tcs.metadata.AbstractLanguage;
import org.eclipse.gmt.tcs.metadata.Language;
import org.eclipse.gmt.tcs.metadata.LanguageSource;
import org.eclipse.gmt.tcs.metadata.ModelFactory;
-import org.eclipse.gmt.tcs.metadata.VMLauncher;
-import org.eclipse.m2m.atl.core.IModel;
-import org.eclipse.m2m.atl.core.IReferenceModel;
-import org.eclipse.m2m.atl.core.emf.EMFInjector;
-import org.eclipse.m2m.atl.core.emf.EMFModelFactory;
import org.eclipse.m2m.atl.core.launch.ILauncher;
-import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel;
-import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModelElement;
-import org.eclipse.m2m.atl.drivers.emf4atl.EMFModelLoader;
import org.eclipse.m2m.atl.dsls.DSLResourceProvider;
import org.eclipse.m2m.atl.dsls.textsource.IFileTextSource;
import org.eclipse.m2m.atl.dsls.textsource.TextSource;
-import org.eclipse.m2m.atl.engine.emfvm.VMException;
-import org.eclipse.m2m.atl.engine.emfvm.launch.EMFVMLauncher;
-import org.eclipse.m2m.atl.engine.emfvm.lib.AbstractStackFrame;
-import org.eclipse.m2m.atl.engine.emfvm.lib.ExecEnv;
-import org.eclipse.m2m.atl.engine.emfvm.lib.LibExtension;
-import org.eclipse.m2m.atl.engine.emfvm.lib.Operation;
-import org.eclipse.m2m.atl.engine.emfvm.lib.Tuple;
import org.eclipse.m2m.atl.engine.vm.ASM;
import org.eclipse.m2m.atl.engine.vm.ASMXMLReader;
-import org.eclipse.m2m.atl.engine.vm.AtlModelHandler;
-import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;
/**
*
* @author Frédéric Jouault
*/
-public class WorkspaceLanguage implements Language, LanguageSource {
+public class WorkspaceLanguage extends AbstractLanguage implements Language, LanguageSource {
private static class ModelCacheFromIFile extends ModelCache {
private String metamodelName;
@@ -225,227 +199,6 @@ public class WorkspaceLanguage implements Language, LanguageSource {
return this;
}
- public Object inject(ModelFactory factory, Object model, TextSource source, final Map params) {
- try {
- params.put("name", name);
- // TODO: support multiple parserGenerators
- //params.put("parserGenerator", getParserGenerator()); // not specifying any parserGenerator will default to antlr3
-
- Object metamodel = getMetamodel(factory);
-
- // Grab a reference to problemModel now, because if we get it after the injection,
- // it may have been replaced by a model adapter.
- Object problemModel = params.get("problems");
-
- if(model == null) {
- model = factory.newModel("model.xmi", metamodel);
- }
- final Object model_ = model;
-
- final Map hyperlinks = (Map)params.get("hyperlinks");
- final Map locations = (Map)params.get("locationByElement");
- Map trace_ = (Map)params.get("trace");
- if((hyperlinks != null) && (trace_ == null)) {
- trace_ = new HashMap();
- params.put("trace", trace_);
- }
- final Map trace = trace_;
-
- final VirtualModelAdapter vma = new VirtualModelAdapter(new ASMModelAdapter(model));
- params.put("modelAdapter", vma);
-
- Object ret = TCSInjection.inject(factory, model, metamodel, source, params, jarFile.getLocationURI().toURL());
-
- if(problemModel != null) {
- // TODO: only if no parsing error?
- VMLauncher vmLauncher = (VMLauncher)params.get("vmLauncher");
- if(vmLauncher != null) {
- IFile wfrFile = project.getFile("WFR/" + name + ".asm");
- if(wfrFile.exists()) {
- /*
- Map libraries = new HashMap();
- libraries.put("TCSVirtualProperties", vma.getLibrary(name));
- String libNameAndPathsCSV = getProperty("wfr.libraries");
- if(libNameAndPathsCSV != null) {
- String libNameAndPaths[] = libNameAndPathsCSV.split(",");
- for(int i = 0 ; i < libNameAndPaths.length ; i++) {
- String parts[] = libNameAndPaths[i].split("=");
- libraries.put(parts[0], project.getFile(parts[1]).getLocationURI().toURL());
- }
- }
- Map models = new HashMap();
- models.put(name, metamodel);
- models.put("IN", ret);
- models.put("Problem", factory.metamodelOf(problemModel));
- models.put("OUT", problemModel);
- vmLauncher.launch(wfrFile.getLocationURI().toURL(), models, libraries);
- */
- // override VM Launcher to use EMFVM
- ILauncher launcher = new EMFVMLauncher();
- launcher.initialize(Collections.emptyMap());
-
- EMFModelFactory emfFac = new EMFModelFactory();
-
- IReferenceModel pbMM = emfFac.newReferenceModel();
- new EMFInjector().inject(pbMM, ((ASMEMFModel)factory.metamodelOf(problemModel)).getExtent());
-
- IReferenceModel mm = emfFac.newReferenceModel();
- new EMFInjector().inject(mm, ((ASMEMFModel)factory.metamodelOf(model)).getExtent());
-
- IModel m = emfFac.newModel(mm);
- new EMFInjector().inject(m, ((ASMEMFModel)model).getExtent());
-
- IModel pbM = emfFac.newModel(pbMM);
- new EMFInjector().inject(pbM, ((ASMEMFModel)problemModel).getExtent());
-
- launcher.addInModel(mm, name, "MOF");
- launcher.addInModel(m, "IN", name);
- launcher.addInModel(pbMM, "Problem", "MOF");
- launcher.addOutModel(pbM, "OUT", "Problem");
-
- String libNameAndPathsCSV = getProperty("wfr.libraries");
- try {
- if(libNameAndPathsCSV != null) {
- String libNameAndPaths[] = libNameAndPathsCSV.split(",");
- for(int i = 0 ; i < libNameAndPaths.length ; i++) {
- String parts[] = libNameAndPaths[i].split("=");
- launcher.addLibrary(parts[0], project.getFile(parts[1]).getLocationURI().toURL().openStream());
- }
- }
-
- Map options = new HashMap();
- List extensionObjects = new ArrayList();
- extensionObjects.add(new LibExtension() {
- public void apply(ExecEnv execEnv, Map options) {
- // allVirtualProperties global/context-less helper => not possible here because ASMModule
- // only created after extensions are called.
- // Workaround: register on String (for no specific reason (could be any other type)).
- final Set allProperties = vma.getAllProperties();
-
- // We keep document order. Until GenericResolver can topologically sort, we must make sure to return in the same order.
- // Actually, it should be metamodel order (closer to external resolver with specific metamodel), but document order is even better
- // (closer to internal resolver, and therefore same best practices, such as only looking in a reference resolved before, apply).
- execEnv.registerOperation(String.class, new Operation(1, "allVirtualProperties") {
- public Object exec(AbstractStackFrame frame) {
- return allProperties;
- }
- });
-
- if(params.containsKey("hyperlinks")) {
- execEnv.registerOperation(String.class, new Operation(4, "addHyperlink") {
- public Object exec(AbstractStackFrame frame) {
- Object locals[] = frame.getLocalVars();
- // TODO: generalize this
- Object source = ((ASMEMFModel)model_).getASMModelElement((EObject)locals[1]);
- Object target = ((ASMEMFModel)model_).getASMModelElement((EObject)locals[3]);
- hyperlinks.put(
- ((ElementTrace)trace.get(source)).getPropertyLocation((String)locals[2]),
- locations.get(target)
- );
- return null;
- }
- });
- }
-
- // register weaving helpers used to represent virtual properties
- for(Iterator i = allProperties.iterator() ; i.hasNext() ; ) {
- Tuple t = (Tuple)i.next();
- Object type = t.get(null, "eContainingClass");
- String name = (String)t.get(null, "name");
- execEnv.registerWeavingHelper(type, name, null);
- }
-
- // store values
- for(Iterator i = vma.getVirtualProperties().entrySet().iterator() ; i.hasNext() ; ) {
- Map.Entry ei = (Map.Entry)i.next();
- Object element = ei.getKey();
- if(element instanceof ASMEMFModelElement) {
- element = ((ASMEMFModelElement)element).getObject();
- }
- // <String, Object>
- Map slots = (Map)ei.getValue();
- for(Iterator j = slots.entrySet().iterator() ; j.hasNext() ; ) {
- Map.Entry ej = (Map.Entry)j.next();
- String propertyName = (String)ej.getKey();
- Object value = ej.getValue();
- execEnv.setHelperValue(element, propertyName, value);
- }
- }
- }
- });
-
- options.put("extensionObjects", extensionObjects);
- launcher.launch(ILauncher.RUN_MODE, null, options, new Object[] {wfrFile.getLocationURI().toURL().openStream()});
- } catch(IOException ioe) {
- throw new RuntimeException("could not run WFR transformation", ioe);
- } catch(VMException vme) {
- vme.printStackTrace();
- }
- }
- }
- }
- if(hyperlinks != null) {
- // Change target to location of "name" attribute if it exists.
-
- // TODO:
- // - make this optional
- // - make this generic (i.e., use refersTo information)
- // - make it doable from transformation (need to represent ElementTraces as model)
-
- Map newLocationFromOld = new HashMap(); // only for those that change
- for(Iterator i = locations.entrySet().iterator() ; i.hasNext() ; ) {
- Map.Entry entry = (Map.Entry)i.next();
- Object element = entry.getKey();
- ElementTrace et = (ElementTrace)trace.get(element);
- if(et != null) {
- Object newLocation = et.getPropertyLocation("name");
- if(newLocation != null) {
- Object oldLocation = entry.getValue();
- newLocationFromOld.put(oldLocation, newLocation);
- }
- } else {
- // e.g., auto-created elements
- }
- }
-
- // Remarks:
- // - after this transformation, text hovers may be incomplete if hyperlinks are used for this purpose
- // => therefore special "ofn=" (old from new) hyperlinks are added
- Map oldLocationFromNew = new HashMap();
- for(Iterator i = hyperlinks.entrySet().iterator() ; i.hasNext() ; ) {
- Map.Entry entry = (Map.Entry)i.next();
- Object oldTarget = entry.getValue();
- Object newTarget = newLocationFromOld.get(oldTarget);
- if(newTarget != null) {
- entry.setValue(newTarget);
- oldLocationFromNew.put("ofn=" + newTarget, oldTarget);
- }
- }
- hyperlinks.putAll(oldLocationFromNew);
- }
-
- return ret;
- } catch (MalformedURLException e) {
- throw new RuntimeException("Could not inject", e);
- }
- }
-
- public void extract(ModelFactory factory, Object model, OutputStream out, Map params) {
- EMFModelLoader ml = (EMFModelLoader)AtlModelHandler.getDefault(AtlModelHandler.AMH_EMF).createModelLoader();
- ASMModel tcsMetamodel;
- try {
- tcsMetamodel = ml.loadModel("TCS", ml.getMOF(), DSLResourceProvider.getDefault().getResource("TCS/Metamodel/TCS.ecore").asEMFURI());
- } catch(IOException ioe) {
- throw new RuntimeException("Could not load TCS metamodel", ioe);
- }
- ASMModel format = ml.newModel("syntax", "model.xmi", tcsMetamodel);
- Map oparams = new HashMap();
- oparams.put("name", "TCS");
- TCSInjection.inject(factory, format, tcsMetamodel, new IFileTextSource(tcsFile), oparams, DSLResourceProvider.getDefault().getResource("TCS/Syntax/TCS-parser.jar").asURL());
- params.put("format", format);
- new TCSExtractor().extract((ASMModel)model, out, params);
- }
-
public String getExtension() {
return extension;
}
@@ -534,4 +287,72 @@ public class WorkspaceLanguage implements Language, LanguageSource {
public IFile getCompilerFile() {
return compilerFile;
}
+
+ private void addLibraries(ILauncher launcher, String propertyName) throws IOException {
+ String libNameAndPathsCSV = this.getProperty("wfr.libraries");
+
+ if(libNameAndPathsCSV != null) {
+ String libNameAndPaths[] = libNameAndPathsCSV.split(",");
+ for(int i = 0 ; i < libNameAndPaths.length ; i++) {
+ String parts[] = libNameAndPaths[i].split("=");
+ launcher.addLibrary(parts[0], project.getFile(parts[1]).getLocationURI().toURL().openStream());
+ }
+ }
+ }
+
+ protected void addWFRLibraries(ILauncher launcher) throws IOException {
+ this.addLibraries(launcher, "wfr.libraries");
+ }
+
+ protected void addPreExtractLibraries(ILauncher launcher) throws IOException {
+ this.addLibraries(launcher, "pre-extract.libraries");
+ }
+
+ private IFile getFile(String path) {
+ return project.getFile(path);
+ }
+
+ private InputStream getASM(String path) throws IOException {
+ IFile wfrFile = getFile(path);
+ if(wfrFile.exists()) {
+ return wfrFile.getLocationURI().toURL().openStream();
+ } else {
+ return null;
+ }
+ }
+
+ protected boolean hasWFR() {
+ return this.getFile("WFR/" + name + ".asm").exists();
+ }
+
+ protected InputStream getWFR() throws IOException {
+ return this.getASM("WFR/" + name + ".asm");
+ }
+
+ protected boolean hasPreExtract() {
+ return this.getFile("WFR/PreExtract.asm").exists();
+ }
+
+ protected InputStream getPreExtract() throws IOException {
+ return this.getASM("WFR/PreExtract.asm");
+ }
+
+ protected void addExtractOptions(Map params) {
+ String opts = getProperty("extract.options");
+ if(opts != null) {
+ String optsParts[] = opts.split(",");
+ for(int i = 0 ; i < optsParts.length ; i++) {
+ String mapping[] = optsParts[i].split("=");
+ params.put(mapping[0], mapping[1]);
+ }
+ }
+ }
+
+ protected TextSource getTCS() {
+ return new IFileTextSource(tcsFile);
+ }
+
+ protected URL getJarURL() throws MalformedURLException {
+ return jarFile.getLocationURI().toURL();
+ }
}

Back to the top