/**
* Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis,
* Rick Salay.
* 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:
* Alessio Di Sandro - Implementation.
*/
package edu.toronto.cs.se.modelepedia.z3.operator.henshin;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.interpreter.EGraph;
import org.eclipse.emf.henshin.interpreter.Engine;
import org.eclipse.emf.henshin.interpreter.Match;
import org.eclipse.emf.henshin.interpreter.RuleApplication;
import org.eclipse.emf.henshin.interpreter.impl.EGraphImpl;
import org.eclipse.emf.henshin.interpreter.impl.EngineImpl;
import org.eclipse.emf.henshin.interpreter.impl.RuleApplicationImpl;
import org.eclipse.emf.henshin.model.Module;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.emf.henshin.model.Unit;
import org.eclipse.emf.henshin.model.resource.HenshinResourceSet;
import org.eclipse.emf.henshin.trace.Trace;
import org.eclipse.jdt.annotation.NonNull;
import edu.toronto.cs.se.mmint.MMINTException;
import edu.toronto.cs.se.mmint.MIDTypeHierarchy;
import edu.toronto.cs.se.mmint.MIDTypeRegistry;
import edu.toronto.cs.se.mmint.mid.GenericElement;
import edu.toronto.cs.se.mmint.mid.MID;
import edu.toronto.cs.se.mmint.mid.Model;
import edu.toronto.cs.se.mmint.mid.operator.impl.OperatorImpl;
import edu.toronto.cs.se.mmint.mid.relationship.BinaryModelRel;
import edu.toronto.cs.se.mmint.mid.utils.FileUtils;
import edu.toronto.cs.se.mmint.mid.utils.MIDOperatorIOUtils;
//TODO MMINT[OPERATOR] Move to appropriate package+feature when they're created for core operators
//TODO MMINT[OPERATOR] Use this as base for the lifted ones
public class HenshinTransformation extends OperatorImpl {
// input-output
private final static @NonNull String IN_MODEL = "original";
private final static @NonNull String OUT_MODEL = "transformed";
private final static @NonNull String OUT_MODELREL = "trace";
private final static @NonNull String PROPERTY_IN_HENSHINFILENAME = "henshinFileName";
// constants
private final static @NonNull String TRANSFORMED_MODEL_SUFFIX = "_transformed";
// input
private String henshinFileName;
@Override
public void readInputProperties(Properties inputProperties) throws MMINTException {
henshinFileName = MIDOperatorIOUtils.getStringProperty(inputProperties, PROPERTY_IN_HENSHINFILENAME);
}
private EObject transform(Model originalModel) throws MMINTException {
// init
String originalModelDirectoryUri = FileUtils.prependWorkspacePathToUri(
FileUtils.replaceLastSegmentInUri(originalModel.getUri(), ""));
HenshinResourceSet hResourceSet = new HenshinResourceSet(originalModelDirectoryUri);
Module hModule = hResourceSet.getModule(henshinFileName, false);
Engine hEngine = new EngineImpl();
hEngine.getOptions().put(Engine.OPTION_SORT_VARIABLES, false);
EGraph hGraph = new EGraphImpl(hResourceSet.getResource(FileUtils.getLastSegmentFromUri(
originalModel.getUri())));
// apply rules
for (Unit hUnit : hModule.getUnits()) {
if (!(hUnit instanceof Rule)) {
// TODO MMINT[HENSHIN] Add support for other constructs
continue;
}
Rule hRule = (Rule) hUnit;
RuleApplication hApplication = new RuleApplicationImpl(hEngine);
hApplication.setRule(hRule);
hApplication.setEGraph(hGraph);
for (Match hMatch : hEngine.findMatches(hRule, hGraph, null)) {
hApplication.setCompleteMatch(hMatch);
hApplication.execute(null);
}
}
// get result
EObject transformedRootModelObj = null;
for (EObject hRoot : hGraph.getRoots()) {
if (hRoot instanceof Trace) {
continue;
}
transformedRootModelObj = hRoot;
}
if (transformedRootModelObj == null) {
throw new MMINTException("Can't retrieve transformed root model object");
}
return transformedRootModelObj;
}
@Override
public Map<String, Model> run(
Map<String, Model> inputsByName, Map<String, GenericElement> genericsByName,
Map<String, MID> outputMIDsByName) throws Exception {
// input
Model origModel = inputsByName.get(IN_MODEL);
// transform
EObject transformedRootModelObj = transform(origModel);
// output
String transformedModelUri = FileUtils.getUniqueUri(
FileUtils.addFileNameSuffixInUri(origModel.getUri(), TRANSFORMED_MODEL_SUFFIX),
true,
false);
FileUtils.writeModelFile(transformedRootModelObj, transformedModelUri, true);
Model transformedModelType = MIDTypeRegistry.getType(
transformedRootModelObj.eClass().getEPackage().getNsURI());
Model transformedModel = transformedModelType.createInstanceAndEditor(
transformedModelUri,
outputMIDsByName.get(OUT_MODEL));
BinaryModelRel traceRel = MIDTypeHierarchy.getRootModelRelType().createBinaryInstanceAndEndpoints(
null,
origModel,
transformedModel,
outputMIDsByName.get(OUT_MODELREL));
traceRel.setName(OUT_MODELREL);
Map<String, Model> outputsByName = new HashMap<>();
outputsByName.put(OUT_MODEL, transformedModel);
outputsByName.put(OUT_MODELREL, traceRel);
return outputsByName;
}
}