blob: fa1beb365667abfe3b4df979904a6643c406d0d4 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2018 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.moka.ease.parametric;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.papyrus.moka.composites.CompositeStructuresExecutionEngine;
import org.eclipse.papyrus.moka.composites.Semantics.impl.Loci.LociL3.CS_Executor;
import org.eclipse.papyrus.moka.composites.interfaces.Semantics.CompositeStructures.StructuredClasses.ICS_Object;
import org.eclipse.papyrus.moka.ease.semantics.proxy.LoggedValue;
import org.eclipse.papyrus.moka.ease.semantics.proxy.MapProxy;
import org.eclipse.papyrus.moka.ease.semantics.proxy.ParametricInstanceSpecGenerator;
import org.eclipse.papyrus.moka.ease.semantics.proxy.ScriptProxy;
import org.eclipse.papyrus.moka.ease.semantics.proxy.TimeValue;
import org.eclipse.papyrus.moka.engine.IExecutionEngine;
import org.eclipse.papyrus.moka.fuml.Semantics.Classes.Kernel.IFeatureValue;
import org.eclipse.papyrus.moka.fuml.Semantics.Classes.Kernel.IObject_;
import org.eclipse.papyrus.moka.fuml.Semantics.Classes.Kernel.IValue;
import org.eclipse.papyrus.moka.fuml.Semantics.Loci.LociL1.ILocus;
import org.eclipse.papyrus.moka.fuml.Semantics.impl.Classes.Kernel.Object_;
import org.eclipse.papyrus.moka.fuml.Semantics.impl.Classes.Kernel.Reference;
import org.eclipse.papyrus.moka.parametric.semantics.ParametricConstructStrategy;
import org.eclipse.papyrus.moka.parametric.semantics.ParametricExecutionFactory;
import org.eclipse.papyrus.moka.parametric.semantics.ParametricLocus;
import org.eclipse.papyrus.moka.parametric.semantics.ParametricObject;
import org.eclipse.papyrus.moka.service.IMokaService;
import org.eclipse.papyrus.moka.service.MokaServiceRegistry;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.InstanceValue;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.ValueSpecification;
public class QuietCausalParametricInterpreter extends CompositeStructuresExecutionEngine implements IExecutionEngine {
private InstanceSpecification result;
private List<ParametricObject> objectsToEvalFirst;
private IObject_ object;
List<Double> time;
List<LoggedValue> log = new ArrayList<>();
private MapProxy proxyObject;
public QuietCausalParametricInterpreter() {
// nothing to do
}
@Override
public ILocus initializeLocus() {
ILocus locus = new ParametricLocus();
locus.setExecutor(new CS_Executor());
locus.setFactory(new ParametricExecutionFactory());
return locus;
}
// Register semantic strategies available in the environment
@Override
protected void registerSemanticStrategies(ILocus locus) {
super.registerSemanticStrategies(locus);
locus.getFactory().setStrategy(new ParametricConstructStrategy());
}
@Override
public void start(IProgressMonitor monitor) {
if (!mode.equals(OperatingMode.QUIET)) {
// Initialize every service with the parameters of this particular run
MokaServiceRegistry registry = MokaServiceRegistry.getInstance();
registry.loadServices();
for (IMokaService service : registry.getAllServices()) {
service.init(this.launch, executionEntryPoint);
}
}
if (this.executionEntryPoint != null && this.executionEntryPoint instanceof InstanceSpecification) {
initEngine();
// Launches the execution/evaluation
IObject_ o = this.evaluateInstanceSpecification((InstanceSpecification) this.executionEntryPoint);
// Serialize the object in the papyrus model as an instance spec
ValueSpecification v = o.specify();
result = ((InstanceValue) v).getInstance();
}
}
private void initEngine() {
this.locus = this.initializeLocus();
// initializes built-in primitive types
this.initializeBuiltInPrimitiveTypes(locus);
// Initializes opaque behavior executions
this.registerOpaqueBehaviorExecutions(locus);
// Initializes system services
this.registerSystemServices(locus);
// Initializes semantic strategies
this.registerSemanticStrategies(locus);
// Initializes arguments
this.initializeArguments(this.executionArgs);
log.clear();
}
public Object initEngine(Class constraintClass) {
ParametricInstanceSpecGenerator generator = new ParametricInstanceSpecGenerator(
UMLFactory.eINSTANCE.createPackage(), false);
executionEntryPoint = generator.generateInstanceSpecification(constraintClass);
initEngine();
return ScriptProxy.getKernelAdapter()
.getProxyFor(constructObjects((InstanceSpecification) executionEntryPoint));
}
public Object initEngine(InstanceSpecification instSpec) {
executionEntryPoint = instSpec;
initEngine();
return ScriptProxy.getKernelAdapter()
.getProxyFor(constructObjects((InstanceSpecification) executionEntryPoint));
}
/**
* Single step evaluation
* @return the root Object of the locus
*/
public IObject_ evaluate() {
if (this.containsParametricObjects(object)) {
for (ParametricObject o : objectsToEvalFirst) {
o.evaluate();
}
}
if (object instanceof ParametricObject) {
((ParametricObject) object).evaluate();
}
logValues();
return object;
}
/**
* Multiple steps evaluation
* @return the root Object of the locus
*/
public IObject_ evaluate(int steps) {
//we log initial values
logValues();
for (int i = 0; i < steps; i++) {
evaluate();
}
return object;
}
/**
* Multiple steps evaluation
* @return the root Object of the locus
*/
public IObject_ evaluate(double startTime, double endTime, double dt) {
//we create a time value vector
TimeValue time = new TimeValue(startTime, dt);
log.add(time);
//we log initial values
logValues();
while (time.getValue() <= endTime) {
//evalue will call logValues, which automatically increments time
evaluate();
}
return object;
}
/**
* Enables the recording of a given variable in the locus
* @param variablePath : the "." separated feature path to the variable to log
* @param alias : an alias for the variable name
*/
public void log(String variablePath, String alias) {
log.add(new LoggedValue(variablePath, alias, proxyObject));
}
/**
* Enables the recording of a given variable in the locus, using the variable path as default alias
* @param variablePath : the "." separated feature path to the variable to log
*/
public void log(String variablePath) {
log(variablePath, variablePath);
}
/**
*
* @return the log containing logged values
*/
public List<LoggedValue> getLog() {
return log;
}
/**
* This method forces the recording of the current value for all logged values
*/
public void logValues() {
for (LoggedValue loggedValue : log) {
loggedValue.logValue();
}
}
private IObject_ constructObjects(InstanceSpecification instance) {
object = this.locus.instantiate((Class) instance.getClassifiers().get(0));
ParametricConstructStrategy strategy = (ParametricConstructStrategy) this.locus.getFactory()
.getStrategy("constructStrategy"); //$NON-NLS-1$
strategy.constructObject((ICS_Object) object, (Class) object.getTypes().get(0));
if (object instanceof ParametricObject) {
((ParametricObject) object).setSourceInstanceSpec(instance);
}
List<Slot> instanceSlots = instance.getSlots();
for (int i = 0; i < instanceSlots.size(); i++) {
Slot slot = instanceSlots.get(i);
List<IValue> values = new ArrayList<IValue>();
List<ValueSpecification> slotValues = slot.getValues();
for (int j = 0; j < slotValues.size(); j++) {
ValueSpecification slotValue = slotValues.get(j);
values.add(this.locus.getExecutor().evaluate(slotValue));
}
object.setFeatureValue(slot.getDefiningFeature(), values, 0);
}
objectsToEvalFirst = this.computeEvalList((Object_) object);
proxyObject = (MapProxy) ScriptProxy.getKernelAdapter().getProxyFor(object);
return object;
}
public IObject_ evaluateInstanceSpecification(InstanceSpecification instance) {
if (instance.getClassifiers().isEmpty())
return null;
constructObjects(instance);
evaluate();
return object;
}
protected boolean containsParametricObjects(IObject_ object) {
if (object instanceof ParametricObject) {
return true;
}
for (IFeatureValue featureValues : object.getFeatureValues()) {
for (IValue v : featureValues.getValues()) {
if (v instanceof Reference) {
IObject_ obj = ((Reference) v).getReferent();
if (obj instanceof ParametricObject) {
return true;
}
return containsParametricObjects(obj);
}
}
}
return false;
}
protected List<ParametricObject> computeEvalList(Object_ object) {
List<ParametricObject> objectsToEvalFirst = new ArrayList<ParametricObject>();
for (IFeatureValue featureValues : object.getFeatureValues()) {
for (IValue v : featureValues.getValues()) {
if (v instanceof Reference) {
IObject_ obj = ((Reference) v).getReferent();
if (obj instanceof ParametricObject) {
objectsToEvalFirst.add((ParametricObject) obj);
}
objectsToEvalFirst.addAll(0, this.computeEvalList((Object_) obj));
}
}
}
return objectsToEvalFirst;
}
protected class SerializeComputationResultCommand extends RecordingCommand {
private final InstanceSpecification computed;
private final InstanceSpecification sourceInstanceSpec;
public SerializeComputationResultCommand(TransactionalEditingDomain domain, InstanceSpecification computed,
InstanceSpecification sourceInstanceSpec) {
super(domain);
this.computed = computed;
this.sourceInstanceSpec = sourceInstanceSpec;
}
private boolean serializeComputationResult(InstanceSpecification computed, InstanceSpecification source) {
// For serialization, a new package is created
// New instance specifications are created (even if instance specifications
// related to the new instance spec could be reused)
Package nearestPackage = source.getNearestPackage();
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// dd/MM/yyyy //$NON-NLS-1$
Date now = new Date();
String strDate = sdfDate.format(now);
Package resultPackage = nearestPackage.createNestedPackage("" + source.getName() + " - Exec - " + strDate); //$NON-NLS-1$ //$NON-NLS-2$
List<InstanceSpecification> toBeAdded = new ArrayList<InstanceSpecification>();
toBeAdded.add(computed);
while (!toBeAdded.isEmpty()) {
InstanceSpecification instance = toBeAdded.remove(0);
if (instance.getModel() == null) {
resultPackage.getPackagedElements().add(instance);
// instance.setName(! instance.getClassifiers().isEmpty() ?
// instance.getClassifiers().get(0).getName() : "null") ;
}
for (Slot s : instance.getSlots()) {
for (ValueSpecification v : s.getValues()) {
if (v instanceof InstanceValue) {
toBeAdded.add(((InstanceValue) v).getInstance());
}
}
}
}
computed.setName("" + sourceInstanceSpec.getName()); //$NON-NLS-1$
return true;
}
@Override
protected void doExecute() {
serializeComputationResult(computed, sourceInstanceSpec);
}
}
public InstanceSpecification getResult() {
return result;
}
}