diff --git a/plugins/de.cau.cs.kieler.sccharts/META-INF/MANIFEST.MF b/plugins/de.cau.cs.kieler.sccharts/META-INF/MANIFEST.MF index 10b0563472..4b985745b9 100644 --- a/plugins/de.cau.cs.kieler.sccharts/META-INF/MANIFEST.MF +++ b/plugins/de.cau.cs.kieler.sccharts/META-INF/MANIFEST.MF @@ -54,6 +54,8 @@ Require-Bundle: org.eclipse.emf.ecore;visibility:=reexport, org.eclipse.core.resources, org.eclipse.core.runtime, org.eclipse.elk.graph;bundle-version="0.4.0", - org.eclipse.elk.core;bundle-version="0.4.0" + org.eclipse.elk.core;bundle-version="0.4.0", + com.google.gson;bundle-version="[2.11.0,3.0.0)" Bundle-ActivationPolicy: lazy -Import-Package: org.apache.log4j +Import-Package: com.google.gson;version="[2.11.0,3.0.0)", + org.apache.log4j diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Action.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Action.java new file mode 100644 index 0000000000..a710a9fbab --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Action.java @@ -0,0 +1,156 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.HashMap; +import java.util.Map; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Action { + + @SerializedName("label") + @Expose + private String label; + /** + * + * (Required) + * + */ + @SerializedName("type") + @Expose + private Action.Type type; + /** + * + * (Required) + * + */ + @SerializedName("isImmediate") + @Expose + private boolean isImmediate; + @SerializedName("guard") + @Expose + private String guard; + /** + * + * (Required) + * + */ + @SerializedName("action") + @Expose + private String action; + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + /** + * + * (Required) + * + */ + public Action.Type getType() { + return type; + } + + /** + * + * (Required) + * + */ + public void setType(Action.Type type) { + this.type = type; + } + + /** + * + * (Required) + * + */ + public boolean isIsImmediate() { + return isImmediate; + } + + /** + * + * (Required) + * + */ + public void setIsImmediate(boolean isImmediate) { + this.isImmediate = isImmediate; + } + + public String getGuard() { + return guard; + } + + public void setGuard(String guard) { + this.guard = guard; + } + + /** + * + * (Required) + * + */ + public String getAction() { + return action; + } + + /** + * + * (Required) + * + */ + public void setAction(String action) { + this.action = action; + } + + @Generated("jsonschema2pojo") + public enum Type { + + @SerializedName("during") + DURING("during"), + @SerializedName("entry") + ENTRY("entry"), + @SerializedName("exit") + EXIT("exit"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Action.Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + public String value() { + return this.value; + } + + public static Action.Type fromValue(String value) { + Action.Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Reference.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Reference.java new file mode 100644 index 0000000000..c33d950c5b --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Reference.java @@ -0,0 +1,76 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.List; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Reference { + + /** + * + * (Required) + * + */ + @SerializedName("targetID") + @Expose + private String targetID; + @SerializedName("targetFile") + @Expose + private String targetFile; + /** + * + * (Required) + * + */ + @SerializedName("parameters") + @Expose + private List parameters; + + /** + * + * (Required) + * + */ + public String getTargetID() { + return targetID; + } + + /** + * + * (Required) + * + */ + public void setTargetID(String targetID) { + this.targetID = targetID; + } + + public String getTargetFile() { + return targetFile; + } + + public void setTargetFile(String targetFile) { + this.targetFile = targetFile; + } + + /** + * + * (Required) + * + */ + public List getParameters() { + return parameters; + } + + /** + * + * (Required) + * + */ + public void setParameters(List parameters) { + this.parameters = parameters; + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Region.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Region.java new file mode 100644 index 0000000000..82f49b3617 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Region.java @@ -0,0 +1,76 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.List; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Region { + + /** + * + * (Required) + * + */ + @SerializedName("id") + @Expose + private String id; + @SerializedName("label") + @Expose + private String label; + /** + * + * (Required) + * + */ + @SerializedName("states") + @Expose + private List states; + + /** + * + * (Required) + * + */ + public String getId() { + return id; + } + + /** + * + * (Required) + * + */ + public void setId(String id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + /** + * + * (Required) + * + */ + public List getStates() { + return states; + } + + /** + * + * (Required) + * + */ + public void setStates(List states) { + this.states = states; + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/SCTXToJSON.xtend b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/SCTXToJSON.xtend new file mode 100644 index 0000000000..230d01c4f0 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/SCTXToJSON.xtend @@ -0,0 +1,325 @@ +/* + * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient + * + * http://rtsys.informatik.uni-kiel.de/kieler + * + * Copyright ${year} by + * + Kiel University + * + Department of Computer Science + * + Real-Time and Embedded Systems Group + * + * This code is provided under the terms of the Eclipse Public License (EPL). + */ +package de.cau.cs.kieler.sccharts.processors.json; + +import com.google.gson.GsonBuilder +import com.google.inject.Inject +import de.cau.cs.kieler.kexpressions.Declaration +import de.cau.cs.kieler.kexpressions.ValueType +import de.cau.cs.kieler.kexpressions.ValuedObject +import de.cau.cs.kieler.kexpressions.VariableDeclaration +import de.cau.cs.kieler.kexpressions.keffects.extensions.KEffectsSerializeExtensions +import de.cau.cs.kieler.kicool.compilation.CodeContainer +import de.cau.cs.kieler.kicool.compilation.Processor +import de.cau.cs.kieler.kicool.compilation.ProcessorType +import de.cau.cs.kieler.sccharts.ControlflowRegion +import de.cau.cs.kieler.sccharts.DelayType +import de.cau.cs.kieler.sccharts.DuringAction +import de.cau.cs.kieler.sccharts.EntryAction +import de.cau.cs.kieler.sccharts.ExitAction +import de.cau.cs.kieler.sccharts.LocalAction +import de.cau.cs.kieler.sccharts.PreemptionType +import de.cau.cs.kieler.sccharts.Region +import de.cau.cs.kieler.sccharts.SCCharts +import de.cau.cs.kieler.sccharts.State +import de.cau.cs.kieler.sccharts.extensions.SCChartsCoreExtensions +import de.cau.cs.kieler.sccharts.extensions.SCChartsReferenceExtensions +import de.cau.cs.kieler.sccharts.extensions.SCChartsTransitionExtensions +import java.util.HashSet +import java.util.LinkedList +import java.util.List +import java.util.Set + +import static extension java.lang.String.format + +/** + * + */ +public class SCTXToJSON extends Processor { + + @Inject + extension SCChartsCoreExtensions; + @Inject + extension SCChartsTransitionExtensions; + @Inject + extension KEffectsSerializeExtensions; + @Inject + extension SCChartsReferenceExtensions; + +// @Inject +// extension KExpressionsSerializeExtensions; + int regionCounter = 0; + int stateCounter = 0; + + val String namePrefix = "" + + Set scopeNames = new HashSet(); + + /** + * {@inheritDoc} + */ + override String getId() { + return "de.cau.cs.kieler.sccharts.processors.SCTXToJSON"; + } + + /** + * {@inheritDoc} + */ + override String getName() { + return "SCTX to JSON"; + } + + /** + * {@inheritDoc} + */ + override ProcessorType getType() { + return ProcessorType.EXOGENOUS_TRANSFORMATOR; + } + + /** + * {@inheritDoc} + */ + override void process() { + + val cc = new CodeContainer(); + + val gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + this.sourceModel.rootStates.forEach[collectNames] + this.sourceModel.rootStates.forEach[renameState] + val transformedRoots = this.sourceModel.rootStates.map[transformState]; + val fileName = this.sourceModel.name?.hostcodeSafeName ?: "scchart" + + cc.add(fileName + ".json", gson.toJson(transformedRoots)); + this.setModel(cc); + + } + + /** + * Pre-populate the scopeNames set with names that should not be shadowed + * (i.e. everything that is part of the interface, like the referenced state or variable names. + */ + def void collectNames(State state) { + if (state.reference !== null) { + // TODO: if the target is in the same file as the referencing statement, this causes the target to be renamed + // in the renaming step. Not an issue, but weird. + scopeNames.add(state.reference.target.name.hostcodeSafeName) + } + + for (declaration : state.declarations) { + switch (declaration) { + VariableDeclaration: + declaration.valuedObjects.forEach [ + scopeNames.add(name) + ] + default: { + // Do nothing here + } + } + } + + // iterate down the tree + for (region : state.regions) { + if (region instanceof ControlflowRegion) { + region.states.forEach[collectNames] + } + } + } + + def void renameState(State state) { + val name = if (state.name.nullOrEmpty) { + // Generate a name with a running number if no state name is set + namePrefix + '_stateS' + (stateCounter++) + } else { + var new_name = namePrefix + state.name.hostcodeSafeName + + // Ensure the name is really unique + while (scopeNames.contains(new_name)) { + new_name = namePrefix + state.name.hostcodeSafeName + (stateCounter++) + } + new_name + } + scopeNames.add(name); + + if (name != state.name) { + state.label = state.name + state.name = name + } + + state.regions.forEach[renameRegion] + } + + def void renameRegion(Region region) { + val name = if (region.name.nullOrEmpty) { + // Generate a name with a running number if no region name is set + namePrefix + '_regionR' + (regionCounter++) + } else { + var new_name = namePrefix + region.name.hostcodeSafeName + + // Ensure the name is really unique + while (scopeNames.contains(new_name)) { + new_name = namePrefix + region.name.hostcodeSafeName + (regionCounter++) + } + new_name + } + scopeNames.add(name) + + if (name != region.name) { + region.label = region.name + region.name = name + } + + switch (region) { + ControlflowRegion: { + region.states.forEach[renameState] + } + default: { + } + } + } + + def de.cau.cs.kieler.sccharts.processors.json.Region transformRegion(Region region) { + + switch (region) { + ControlflowRegion: { + val transformed = new de.cau.cs.kieler.sccharts.processors.json.Region() + transformed.id = region.name; + transformed.label = region.label; + transformed.states = region.states.map[transformState] + + transformed + } + default: { + environment.errors.add("Cannot handle region %s of type %s.".format(region.name, region.class.name)) + null + } + } + } + + def de.cau.cs.kieler.sccharts.processors.json.State transformState(State state) { + + val transformed = new de.cau.cs.kieler.sccharts.processors.json.State(); + + transformed.id = state.name + transformed.label = state.label + transformed.actions = state.actions.map[transformAction] + transformed.transitions = state.outgoingTransitions.map[transformTransition] + transformed.variables = state.declarations.flatMap[transformDeclaration].toList + transformed.isInitial = state.isInitial() + transformed.isFinal = state.isFinal() + transformed.isConnector = state.connector + transformed.regions = state.regions.map[transformRegion] + + if (state.reference !== null) { + transformed.reference = new Reference(); + val bindings = state.createBindings + transformed.reference.targetID = state.reference.target?.name + transformed.reference.targetFile = state.reference.target?.eResource()?.URI?.toString + // TODO: maybe add structure to the binding. + transformed.reference.parameters = bindings.map [ + sourceExpression.serialize + " to " + targetValuedObject.serialize + targetIndices?.map [ + "[" + it.serialize + "]" + ].join() + ] + } + + return transformed + } + + def Action transformAction(LocalAction action) { + val transformed = new Action() + + transformed.label = action.label + transformed.type = switch (action) { + DuringAction: + Action.Type.DURING + EntryAction: + Action.Type.ENTRY + ExitAction: + Action.Type.EXIT + default: { + environment.errors.add("Cannot handle action %s of type %s.".format(action.label, action.class.name)) + + null + } + } + + transformed.isImmediate = action.delay.equals(DelayType.IMMEDIATE) + transformed.guard = action.trigger?.serialize?.toString + transformed.action = String.valueOf(action.effects.serialize()) + + return transformed + } + + def Transition transformTransition(de.cau.cs.kieler.sccharts.Transition transition) { + val transformed = new Transition() + + transformed.label = transition.label + transformed.targetID = transition.targetState.name + transformed.isImmediate = transition.delay.equals(DelayType.IMMEDIATE) + transformed.preemption = switch (transition.preemption) { + case PreemptionType.TERMINATION: Transition.Preemption.TERMINATION + case PreemptionType.STRONG: Transition.Preemption.STRONG + case PreemptionType.WEAK: Transition.Preemption.WEAK + case PreemptionType.UNDEFINED: Transition.Preemption.WEAK + } + transformed.history = switch (transition.history) { + case RESET: + false + case DEEP: + true + case SHALLOW: { + environment.errors.add( + "Shallow history for transition %s is not supported. Changing to deep history.".format( + transition.toString())); + true + } + } + transformed.guard = transition.trigger?.serialize?.toString + transformed.action = if(!transition.effects.isEmpty()) transition.effects.serialize?.toString + + return transformed + } + + def List transformDeclaration(Declaration declaration) { + switch (declaration) { + VariableDeclaration: + declaration.valuedObjects.map [ + transformVariable(it, declaration.type, declaration.input, declaration.output) + ] + default: { + environment.errors.add( + "Cannot handle declaration %s of type %s.".format(declaration.toString(), declaration.class.name)) + new LinkedList() + } + } + + } + + def Variable transformVariable(ValuedObject v, ValueType t, boolean isInput, boolean isOutput) { + val transformed = new Variable() + + transformed.id = v.name + transformed.type = t.literal + transformed.initialValue = v.initialValue?.serialize?.toString + transformed.isInput = isInput + transformed.isOutput = isOutput + transformed.cardinalities = v.cardinalities?.map[serialize]?.map[Integer.parseInt(it.toString, 10)] ?: List.of() + + return transformed + } + + protected def hostcodeSafeName(String string) { + if(string === null) return "" + string.replaceAll("[\\s-]", "_") + } +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/State.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/State.java new file mode 100644 index 0000000000..569db889f8 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/State.java @@ -0,0 +1,243 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.List; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class State { + + /** + * + * (Required) + * + */ + @SerializedName("id") + @Expose + private String id; + @SerializedName("label") + @Expose + private String label; + /** + * + * (Required) + * + */ + @SerializedName("actions") + @Expose + private List actions; + /** + * + * (Required) + * + */ + @SerializedName("transitions") + @Expose + private List transitions; + /** + * + * (Required) + * + */ + @SerializedName("variables") + @Expose + private List variables; + /** + * + * (Required) + * + */ + @SerializedName("isInitial") + @Expose + private boolean isInitial; + /** + * + * (Required) + * + */ + @SerializedName("isFinal") + @Expose + private boolean isFinal; + /** + * + * (Required) + * + */ + @SerializedName("isConnector") + @Expose + private boolean isConnector; + /** + * + * (Required) + * + */ + @SerializedName("regions") + @Expose + private List regions; + @SerializedName("reference") + @Expose + private Reference reference; + + /** + * + * (Required) + * + */ + public String getId() { + return id; + } + + /** + * + * (Required) + * + */ + public void setId(String id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + /** + * + * (Required) + * + */ + public List getActions() { + return actions; + } + + /** + * + * (Required) + * + */ + public void setActions(List actions) { + this.actions = actions; + } + + /** + * + * (Required) + * + */ + public List getTransitions() { + return transitions; + } + + /** + * + * (Required) + * + */ + public void setTransitions(List transitions) { + this.transitions = transitions; + } + + /** + * + * (Required) + * + */ + public List getVariables() { + return variables; + } + + /** + * + * (Required) + * + */ + public void setVariables(List variables) { + this.variables = variables; + } + + /** + * + * (Required) + * + */ + public boolean isIsInitial() { + return isInitial; + } + + /** + * + * (Required) + * + */ + public void setIsInitial(boolean isInitial) { + this.isInitial = isInitial; + } + + /** + * + * (Required) + * + */ + public boolean isIsFinal() { + return isFinal; + } + + /** + * + * (Required) + * + */ + public void setIsFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + /** + * + * (Required) + * + */ + public boolean isIsConnector() { + return isConnector; + } + + /** + * + * (Required) + * + */ + public void setIsConnector(boolean isConnector) { + this.isConnector = isConnector; + } + + /** + * + * (Required) + * + */ + public List getRegions() { + return regions; + } + + /** + * + * (Required) + * + */ + public void setRegions(List regions) { + this.regions = regions; + } + + public Reference getReference() { + return reference; + } + + public void setReference(Reference reference) { + this.reference = reference; + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Transition.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Transition.java new file mode 100644 index 0000000000..0978dedf4c --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Transition.java @@ -0,0 +1,193 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.HashMap; +import java.util.Map; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Transition { + + @SerializedName("label") + @Expose + private String label; + /** + * + * (Required) + * + */ + @SerializedName("targetID") + @Expose + private String targetID; + /** + * + * (Required) + * + */ + @SerializedName("isImmediate") + @Expose + private boolean isImmediate; + /** + * + * (Required) + * + */ + @SerializedName("preemption") + @Expose + private Transition.Preemption preemption; + /** + * + * (Required) + * + */ + @SerializedName("history") + @Expose + private boolean history; + @SerializedName("guard") + @Expose + private String guard; + @SerializedName("action") + @Expose + private String action; + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + /** + * + * (Required) + * + */ + public String getTargetID() { + return targetID; + } + + /** + * + * (Required) + * + */ + public void setTargetID(String targetID) { + this.targetID = targetID; + } + + /** + * + * (Required) + * + */ + public boolean isIsImmediate() { + return isImmediate; + } + + /** + * + * (Required) + * + */ + public void setIsImmediate(boolean isImmediate) { + this.isImmediate = isImmediate; + } + + /** + * + * (Required) + * + */ + public Transition.Preemption getPreemption() { + return preemption; + } + + /** + * + * (Required) + * + */ + public void setPreemption(Transition.Preemption preemption) { + this.preemption = preemption; + } + + /** + * + * (Required) + * + */ + public boolean isHistory() { + return history; + } + + /** + * + * (Required) + * + */ + public void setHistory(boolean history) { + this.history = history; + } + + public String getGuard() { + return guard; + } + + public void setGuard(String guard) { + this.guard = guard; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + @Generated("jsonschema2pojo") + public enum Preemption { + + @SerializedName("strong") + STRONG("strong"), + @SerializedName("weak") + WEAK("weak"), + @SerializedName("termination") + TERMINATION("termination"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Transition.Preemption c: values()) { + CONSTANTS.put(c.value, c); + } + } + + Preemption(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + public String value() { + return this.value; + } + + public static Transition.Preemption fromValue(String value) { + Transition.Preemption constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Variable.java b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Variable.java new file mode 100644 index 0000000000..b8211e1e22 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/processors/json/Variable.java @@ -0,0 +1,152 @@ + +package de.cau.cs.kieler.sccharts.processors.json; + +import java.util.List; + +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Variable { + + /** + * + * (Required) + * + */ + @SerializedName("id") + @Expose + private String id; + /** + * + * (Required) + * + */ + @SerializedName("type") + @Expose + private String type; + @SerializedName("initialValue") + @Expose + private Object initialValue; + /** + * + * (Required) + * + */ + @SerializedName("isInput") + @Expose + private boolean isInput; + /** + * + * (Required) + * + */ + @SerializedName("isOutput") + @Expose + private boolean isOutput; + + /** + * + * (Required) + * + */ + @SerializedName("cardinalities") + @Expose + private List cardinalities; + + /** + * @return the cardinalities + */ + public List getCardinalities() { + return cardinalities; + } + + /** + * @param cardinalities the cardinalities to set + */ + public void setCardinalities(List cardinalities) { + this.cardinalities = cardinalities; + } + + /** + * + * (Required) + * + */ + public String getId() { + return id; + } + + /** + * + * (Required) + * + */ + public void setId(String id) { + this.id = id; + } + + /** + * + * (Required) + * + */ + public String getType() { + return type; + } + + /** + * + * (Required) + * + */ + public void setType(String type) { + this.type = type; + } + + public Object getInitialValue() { + return initialValue; + } + + public void setInitialValue(Object initialValue) { + this.initialValue = initialValue; + } + + /** + * + * (Required) + * + */ + public boolean isIsInput() { + return isInput; + } + + /** + * + * (Required) + * + */ + public void setIsInput(boolean isInput) { + this.isInput = isInput; + } + + /** + * + * (Required) + * + */ + public boolean isIsOutput() { + return isOutput; + } + + /** + * + * (Required) + * + */ + public void setIsOutput(boolean isOutput) { + this.isOutput = isOutput; + } + +} diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsProcessorProvider.xtend b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsProcessorProvider.xtend index e834a5e5e1..b824057314 100644 --- a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsProcessorProvider.xtend +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsProcessorProvider.xtend @@ -91,7 +91,8 @@ class SCChartsProcessorProvider implements IProcessorProvider { de.cau.cs.kieler.sccharts.processors.AbortRegion, de.cau.cs.kieler.sccharts.processors.scg.SCGAbortRegionProcessor, de.cau.cs.kieler.sccharts.processors.MethodSignaling, - de.cau.cs.kieler.sccharts.processors.analyzers.SCChartsModelData + de.cau.cs.kieler.sccharts.processors.analyzers.SCChartsModelData, + de.cau.cs.kieler.sccharts.processors.json.SCTXToJSON ] } diff --git a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsSystemProvider.xtend b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsSystemProvider.xtend index 8b66c8cf07..630cb77022 100644 --- a/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsSystemProvider.xtend +++ b/plugins/de.cau.cs.kieler.sccharts/src/de/cau/cs/kieler/sccharts/providers/SCChartsSystemProvider.xtend @@ -68,7 +68,9 @@ class SCChartsSystemProvider implements ISystemProvider { "system/de.cau.cs.kieler.c.sccharts.dataflow.kico", "system/de.cau.cs.kieler.sccharts.simulation.priority.java.legacy.kico", "system/de.cau.cs.kieler.sccharts.simulation.tts.priority.java.legacy.kico", - "system/de.cau.cs.kieler.sccharts.netlist.simulink.kico" + "system/de.cau.cs.kieler.sccharts.netlist.simulink.kico", + "system/de.cau.cs.kieler.sccharts.SCTXToJSON.kico", + "system/de.cau.cs.kieler.sccharts.extended.toJSON.kico" ] } diff --git a/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.SCTXToJSON.kico b/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.SCTXToJSON.kico new file mode 100644 index 0000000000..7915b5d6d4 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.SCTXToJSON.kico @@ -0,0 +1,4 @@ +public system de.cau.cs.kieler.sccharts.SCTXToJSON + label "JSON Generation" + +de.cau.cs.kieler.sccharts.processors.SCTXToJSON diff --git a/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.extended.toJSON.kico b/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.extended.toJSON.kico new file mode 100644 index 0000000000..86a52badb8 --- /dev/null +++ b/plugins/de.cau.cs.kieler.sccharts/system/de.cau.cs.kieler.sccharts.extended.toJSON.kico @@ -0,0 +1,13 @@ +public system de.cau.cs.kieler.sccharts.extended.toJSON + label "JSON generation with preprocessing" + +de.cau.cs.kieler.sccharts.processors.timedautomata + +[ label "SyncCharts" + de.cau.cs.kieler.sccharts.processors.^signal + de.cau.cs.kieler.sccharts.processors.suspend + de.cau.cs.kieler.sccharts.processors.countDelay + de.cau.cs.kieler.sccharts.processors.^pre +] + +de.cau.cs.kieler.sccharts.processors.SCTXToJSON diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationProcessorProvider.xtend b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationProcessorProvider.xtend index 306751a1c1..0be26c8928 100644 --- a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationProcessorProvider.xtend +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationProcessorProvider.xtend @@ -37,7 +37,8 @@ class SimulationProcessorProvider implements IProcessorProvider { de.cau.cs.kieler.simulation.testing.processor.TraceSimulator, de.cau.cs.kieler.simulation.testing.processor.TestSuiteGenerator, de.cau.cs.kieler.simulation.testing.processor.SimpleSimulationBenchmarkRunner, - de.cau.cs.kieler.simulation.testing.processor.JsonBenchmarkRunner + de.cau.cs.kieler.simulation.testing.processor.JsonBenchmarkRunner, + de.cau.cs.kieler.simulation.trace.ktrace.json.TraceToJSON ] } diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationSystemProvider.xtend b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationSystemProvider.xtend index 251850f78a..4fbcb5ed80 100644 --- a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationSystemProvider.xtend +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/providers/SimulationSystemProvider.xtend @@ -31,7 +31,8 @@ class SimulationSystemProvider implements ISystemProvider { "system/de.cau.cs.kieler.simulation.c.kico", "system/de.cau.cs.kieler.simulation.java.kico", "system/de.cau.cs.kieler.simulation.benchmarks.csv.simple.kico", - "system/de.cau.cs.kieler.simulation.benchmarks.json.kico" + "system/de.cau.cs.kieler.simulation.benchmarks.json.kico", + "system/de.cau.cs.kieler.ktrace.toJson.kico" ] } diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Assignment.java b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Assignment.java new file mode 100644 index 0000000000..9e08b35484 --- /dev/null +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Assignment.java @@ -0,0 +1,64 @@ + +package de.cau.cs.kieler.simulation.trace.ktrace.json; + +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Assignment { + + /** + * + * (Required) + * + */ + @SerializedName("variableID") + @Expose + private String variableID; + /** + * + * (Required) + * + */ + @SerializedName("value") + @Expose + private Object value; + + /** + * + * (Required) + * + */ + public String getVariableID() { + return variableID; + } + + /** + * + * (Required) + * + */ + public void setVariableID(String variableID) { + this.variableID = variableID; + } + + /** + * + * (Required) + * + */ + public Object getValue() { + return value; + } + + /** + * + * (Required) + * + */ + public void setValue(Object value) { + this.value = value; + } + +} diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Tick.java b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Tick.java new file mode 100644 index 0000000000..42d33af0b3 --- /dev/null +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Tick.java @@ -0,0 +1,87 @@ + +package de.cau.cs.kieler.simulation.trace.ktrace.json; + +import java.util.List; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Tick { + + /** + * + * (Required) + * + */ + @SerializedName("inputs") + @Expose + private List inputs; + /** + * + * (Required) + * + */ + @SerializedName("outputs") + @Expose + private List outputs; + @SerializedName("id") + @Expose + private String id; + @SerializedName("gotoID") + @Expose + private String gotoID; + + /** + * + * (Required) + * + */ + public List getInputs() { + return inputs; + } + + /** + * + * (Required) + * + */ + public void setInputs(List inputs) { + this.inputs = inputs; + } + + /** + * + * (Required) + * + */ + public List getOutputs() { + return outputs; + } + + /** + * + * (Required) + * + */ + public void setOutputs(List outputs) { + this.outputs = outputs; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getGotoID() { + return gotoID; + } + + public void setGotoID(String gotoID) { + this.gotoID = gotoID; + } + +} diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Trace.java b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Trace.java new file mode 100644 index 0000000000..5387b0aef4 --- /dev/null +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/Trace.java @@ -0,0 +1,39 @@ + +package de.cau.cs.kieler.simulation.trace.ktrace.json; + +import java.util.List; +import javax.annotation.processing.Generated; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@Generated("jsonschema2pojo") +public class Trace { + + /** + * + * (Required) + * + */ + @SerializedName("ticks") + @Expose + private List ticks; + + /** + * + * (Required) + * + */ + public List getTicks() { + return ticks; + } + + /** + * + * (Required) + * + */ + public void setTicks(List ticks) { + this.ticks = ticks; + } + +} diff --git a/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/TraceToJSON.xtend b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/TraceToJSON.xtend new file mode 100644 index 0000000000..f2aba40932 --- /dev/null +++ b/plugins/de.cau.cs.kieler.simulation/src/de/cau/cs/kieler/simulation/trace/ktrace/json/TraceToJSON.xtend @@ -0,0 +1,272 @@ +/* + * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient + * + * http://rtsys.informatik.uni-kiel.de/kieler + * + * Copyright ${year} by + * + Kiel University + * + Department of Computer Science + * + Real-Time and Embedded Systems Group + * + * This code is provided under the terms of the Eclipse Public License (EPL). + */ +package de.cau.cs.kieler.simulation.trace.ktrace.json; + +import com.google.gson.GsonBuilder +import com.google.gson.JsonNull +import com.google.inject.Inject +import de.cau.cs.kieler.kexpressions.BoolValue +import de.cau.cs.kieler.kexpressions.Expression +import de.cau.cs.kieler.kexpressions.FloatValue +import de.cau.cs.kieler.kexpressions.IntValue +import de.cau.cs.kieler.kexpressions.JsonArrayValue +import de.cau.cs.kieler.kexpressions.JsonObjectValue +import de.cau.cs.kieler.kexpressions.NullValue +import de.cau.cs.kieler.kexpressions.extensions.KExpressionsSerializeExtensions +import de.cau.cs.kieler.kexpressions.keffects.Effect +import de.cau.cs.kieler.kexpressions.keffects.extensions.KEffectsSerializeExtensions +import de.cau.cs.kieler.kicool.compilation.CodeContainer +import de.cau.cs.kieler.kicool.compilation.Processor +import de.cau.cs.kieler.kicool.compilation.ProcessorType +import de.cau.cs.kieler.simulation.trace.ktrace.TraceFile +import java.io.File + +import static extension java.lang.String.format +import de.cau.cs.kieler.kexpressions.VectorValue +import de.cau.cs.kieler.kexpressions.StringValue +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import java.lang.reflect.Type +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonParseException +import com.google.gson.JsonSerializer +import com.google.gson.JsonSerializationContext +import de.cau.cs.kieler.kexpressions.keffects.Emission +import java.util.Map +import com.google.gson.JsonObject +import com.google.gson.Gson +import com.google.gson.JsonPrimitive +import de.cau.cs.kieler.kexpressions.OperatorExpression +import java.util.concurrent.StructuredTaskScope.Subtask.State + +/** + * + */ +class TraceToJSON extends Processor { + + @Inject + extension KEffectsSerializeExtensions; + + /** + * {@inheritDoc} + */ + override String getId() { + return "de.cau.cs.kieler.ktrace.TraceToJSON"; + } + + /** + * {@inheritDoc} + */ + override String getName() { + return "Trace file to JSON"; + } + + /** + * {@inheritDoc} + */ + override ProcessorType getType() { + return ProcessorType.EXOGENOUS_TRANSFORMATOR; + } + + /** + * {@inheritDoc} + */ + override process() { + val cc = new CodeContainer(); + + val gson = new GsonBuilder().registerTypeAdapter(Tick, new TickSerializer()).setPrettyPrinting(). + disableHtmlEscaping().serializeNulls().create(); + val transformedRoots = this.sourceModel.traces.map[transformTrace]; + val fileName = "trace" + + println("Processing Resource " + this.sourceModel.eResource) + + cc.add(fileName + ".json", gson.toJson(transformedRoots)); + this.setModel(cc); + } + + def de.cau.cs.kieler.simulation.trace.ktrace.json.Trace transformTrace( + de.cau.cs.kieler.simulation.trace.ktrace.Trace trace) { + val transformed = new de.cau.cs.kieler.simulation.trace.ktrace.json.Trace(); + + transformed.ticks = trace.ticks.map[transformTick] + + transformed + } + + def de.cau.cs.kieler.simulation.trace.ktrace.json.Tick transformTick( + de.cau.cs.kieler.simulation.trace.ktrace.Tick tick) { + val transformed = new de.cau.cs.kieler.simulation.trace.ktrace.json.Tick(); + + transformed.inputs = tick.inputs.map[transformEffect] + transformed.outputs = tick.outputs.map[transformEffect] + + transformed.id = tick.name + transformed.gotoID = tick.goto?.name + + transformed + } + + def de.cau.cs.kieler.simulation.trace.ktrace.json.Assignment transformEffect(Effect effect) { + switch (effect) { + de.cau.cs.kieler.kexpressions.keffects.Assignment: { + val transformed = new de.cau.cs.kieler.simulation.trace.ktrace.json.Assignment() + + transformed.variableID = effect.reference?.valuedObject?.name + effect.reference?.indices?.map [ + "[" + it.serialize + "]" + ].join() + if (transformed.variableID === null) { + environment.errors.add( + "Assignment %s has no target variable.".format(effect.serialize, effect.class.name)) + } + + transformed.value = effect.expression.tryExpressionToValue + + transformed + } + Emission: { + val transformed = new de.cau.cs.kieler.simulation.trace.ktrace.json.Assignment() + transformed.variableID = effect.reference?.valuedObject?.name + if (transformed.variableID === null) { + environment.errors.add( + "Assignment %s has no target variable.".format(effect.serialize, effect.class.name)) + } + transformed.value = switch (effect.newValue) { + case null: + Map.of("present", true) + default: + Map.of( + "present", + true, + "value", + effect.newValue.tryExpressionToValue + ) + } + + transformed + } + default: { + environment.errors.add( + "Cannot handle effect %s of type %s.".format(effect.serialize, effect.class.name)) + null + } + } + } + + protected def Object tryExpressionToValue(Expression assignee) { + switch (assignee) { + BoolValue: + assignee.value + IntValue: + assignee.value + FloatValue: + assignee.value + StringValue: + assignee.value + JsonArrayValue: + assignee.elements + JsonObjectValue: + assignee.membersMap + VectorValue: + assignee.values.map[tryExpressionToValue] + NullValue: + null + OperatorExpression: + if (assignee.subExpressions.size != 1) { + environment.warnings.add("unexpected number of expressions in " + assignee) + assignee.serialize.toString + } else { + val subexpression = assignee.subExpressions.get(0).tryExpressionToValue + if (subexpression instanceof String) { + assignee.operator.literal + subexpression + } else if (subexpression instanceof Integer) { + switch (assignee.operator) { + case ADD: { + subexpression + } + case BITWISE_NOT: { + subexpression.bitwiseNot + } + case NOT: { + subexpression == 0 + } + case SUB: { + - subexpression + } + default: { + environment.warnings.add("unexpected unary expression with operator " + + assignee.operator.literal) + assignee.operator.literal + subexpression + } + } + } else if (subexpression instanceof Double) { + switch (assignee.operator) { + case ADD: { + subexpression + } + case NOT: { + subexpression == 0.0 + } + case SUB: { + - subexpression + } + default: { + environment.warnings.add("unexpected unary expression with operator " + + assignee.operator.literal) + assignee.operator.literal + subexpression + } + } + } else if (subexpression instanceof Boolean) { + switch (assignee.operator) { + case BITWISE_NOT: { + ! subexpression + } + case NOT: { + ! subexpression + } + default: { + environment.warnings.add("unexpected unary expression with operator " + + assignee.operator.literal) + assignee.operator.literal + subexpression + } + } + } + } + default: { + environment.warnings.add("unexpected expression in trace of type " + assignee) + assignee.serialize.toString + } + } + } + +} + +class TickSerializer implements JsonSerializer { + + override serialize(Tick src, Type typeOfSrc, JsonSerializationContext context) { + val obj = new JsonObject() + + obj.add("inputs", context.serialize(src.inputs)) + obj.add("outputs", context.serialize(src.outputs)) + + if (src.id !== null) { + obj.addProperty("id", src.id) + } + if (src.gotoID !== null) { + obj.addProperty("gotoID", src.gotoID) + } + + return obj + } + +} diff --git a/plugins/de.cau.cs.kieler.simulation/system/de.cau.cs.kieler.ktrace.toJson.kico b/plugins/de.cau.cs.kieler.simulation/system/de.cau.cs.kieler.ktrace.toJson.kico new file mode 100644 index 0000000000..7b6732d8a1 --- /dev/null +++ b/plugins/de.cau.cs.kieler.simulation/system/de.cau.cs.kieler.ktrace.toJson.kico @@ -0,0 +1,4 @@ +public system de.cau.cs.kieler.ktrace.toJSON + label "JSON Generation" + +de.cau.cs.kieler.ktrace.TraceToJSON