diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java index e500b3d..8966209 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java @@ -51,6 +51,14 @@ this.pathParams.add(exp); } + public ResourcePath(ResourcePath parent, Expression exp, ResourceHierarchy resourceHierarchy) { + super(parent.toString() + ".{" + exp + "}"); + this.parent = parent; + this.resourceHierarchy = resourceHierarchy; + this.pathParams = new ArrayList<>(parent.getPathParams()); + this.pathParams.add(exp); + } + public ResourcePath(ResourcePath another) { super(another.name); this.parent = another.parent; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index 08eeab5..d21cc49 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -201,7 +201,7 @@ * Derive the state update calculation of the target channel member with a given resource push/pull state accessor. * @param targetMember a channel member whose state is to be updated * @param stateAccessor a push/pull resource state accessor - * @return the derived update calculation + * @return the derived update calculation and the unified message * @throws ParameterizedIdentifierIsFutureWork * @throws ResolvingMultipleDefinitionIsFutureWork * @throws InvalidMessage @@ -233,9 +233,10 @@ } /** - * Fill outside resource paths with a given resource push/pull state accessor. + * Derive the state update calculation of the target channel member with a message and a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param message a message on the channel * @param stateAccessor a push/pull resource state accessor - * @param resourcePaths a container to be returned with filled outside resource paths * @return the derived update calculation * @throws ParameterizedIdentifierIsFutureWork * @throws ResolvingMultipleDefinitionIsFutureWork @@ -243,6 +244,26 @@ * @throws UnificationFailed * @throws ValueUndefined */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, Term message, IResourceStateAccessor stateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + if (!getOutputChannelMembers().contains(targetMember)) return null; + + // Calculate the next state of target resource from the unified message and the current resource state + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetMember, targetMember); + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, message); + } + + /** + * Fill outside resource paths with a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a push/pull resource state accessor + * @return map from a depending channel member to the pair of the filled resource path and the set of the depended channel members + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ public Map>> fillOutsideResourcePaths(ChannelMember targetMember, IResourceStateAccessor stateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { return fillOutsideResourcePaths(targetMember, stateAccessor, null); @@ -254,19 +275,19 @@ Map>> resourcePaths = new HashMap<>(); // Calculate unified message constraints from input and reference state transitions - Map> substitutedPositionsFromChannels = new HashMap<>(); - Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsFromChannels); + Map> substitutedPositionsInMessageFromChannels = new HashMap<>(); + Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); // Fill outside resource paths if (unifiedMessage != null) { for (ChannelMember cm: getInputChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -275,17 +296,17 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } for (ChannelMember cm: getReferenceChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -294,17 +315,17 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } for (ChannelMember cm: getOutputChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -313,15 +334,81 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } } return resourcePaths; } - + + public Map> getMemberDependency() { + Map> dependency = new HashMap<>(); + + // Collect depended channel members and their positions in the message + Map> substitutedPositionsInMessage = getDependedChannelMembersAndTheirPositionsInMessage(); + + // Resolve dependency for each outside resource path + if (substitutedPositionsInMessage != null) { + for (ChannelMember cm: getInputChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + for (ChannelMember cm: getReferenceChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + for (ChannelMember cm: getOutputChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + } + return dependency; + } + private Term calcUnifiedMessage(ChannelMember targetMember, IResourceStateAccessor stateAccessor, - Map inputResourceToStateAccessor, Map> substitutedPositionsFromChannels) + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork, UnificationFailed { Set messageConstraints = new HashSet<>(); @@ -336,9 +423,9 @@ curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); } - Set substitutedPositions = new HashSet<>(); - Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositions); - if (substitutedPositions.size() > 0) substitutedPositionsFromChannels.put(inputMember, substitutedPositions); + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositionsInMessage); + if (substitutedPositionsInMessage.size() > 0) substitutedPositionsInMessageFromChannels.put(inputMember, substitutedPositionsInMessage); messageConstraints.add((Term) messageConstraintByInput); } @@ -352,7 +439,7 @@ } Set substitutedPositions = new HashSet<>(); Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, substitutedPositions); - if (substitutedPositions.size() > 0) substitutedPositionsFromChannels.put(referenceMember, substitutedPositions); + if (substitutedPositions.size() > 0) substitutedPositionsInMessageFromChannels.put(referenceMember, substitutedPositions); messageConstraints.add((Term) messageConstraintByReference); } @@ -370,8 +457,53 @@ } return unifiedMessage; } + + /** + * Get depended channel members and their positions in the message. + * + * @return depended channel members and their positions in the message + */ + private Map> getDependedChannelMembersAndTheirPositionsInMessage() { + Map> channelMembersMessageDependsOn = new HashMap<>(); + // Collect channel members that the message depends on from input state transitions + for (ChannelMember inputMember: getInputChannelMembers()) { + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageTerm = inputMember.getStateTransition().getMessageExpression(); + HashMap messageVars = messageTerm.getVariables(); + for (Entry varEnt: messageVars.entrySet()) { + Variable var = varEnt.getValue(); + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } + } + } + if (substitutedPositionsInMessage.size() > 0) channelMembersMessageDependsOn.put(inputMember, substitutedPositionsInMessage); + } - private ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPos) + // Collect channel members that the message depends on from reference state transitions + for (ChannelMember referenceMember: getReferenceChannelMembers()) { + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageTerm = referenceMember.getStateTransition().getMessageExpression(); + HashMap messageVars = messageTerm.getVariables(); + for (Entry varEnt: messageVars.entrySet()) { + Variable var = varEnt.getValue(); + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } + } + } + if (substitutedPositionsInMessage.size() > 0) channelMembersMessageDependsOn.put(referenceMember, substitutedPositionsInMessage); + } + return channelMembersMessageDependsOn; + } + + private ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPosInMessage) throws ResolvingMultipleDefinitionIsFutureWork { ResourcePath filledResourcePath = new ResourcePath(resource); @@ -383,7 +515,7 @@ Expression valueCalc = unifiedMessage.getSubTerm(varPos); if (valueCalc != null) { if (bindings.get(var) != null) throw new ResolvingMultipleDefinitionIsFutureWork(); - bindings.put(var, new AbstractMap.SimpleEntry(varPos, valueCalc)); + bindings.put(var, new AbstractMap.SimpleEntry<>(varPos, valueCalc)); } } @@ -391,25 +523,51 @@ for (int i = 0; i < filledResourcePath.getPathParams().size(); i++) { Expression pathParam = dstParams.get(i); if (pathParam instanceof Variable) { - dstParams.set(i, bindings.get((Variable) pathParam).getValue()); - dependingVarPos.add(bindings.get((Variable) pathParam).getKey()); - } else { + dstParams.set(i, bindings.get((Variable) pathParam).getValue()); // Replace a path parameter with a value in the unified message. + dependingVarPosInMessage.add(bindings.get((Variable) pathParam).getKey()); // The position of the replaced variable in the message. + } else if (pathParam instanceof Term) { Map pathParamVars = ((Term) pathParam).getVariables(); for (Variable var: bindings.keySet()) { - if (pathParamVars.values().contains(var)) { - pathParam = ((Term) pathParam).substitute(var, bindings.get(var).getValue()); - dependingVarPos.add(bindings.get((Variable) var).getKey()); + if (pathParamVars.values().contains(var)) { // var is a subterm of a path parameter + pathParam = ((Term) pathParam).substitute(var, bindings.get(var).getValue()); // Substitute a value in the unified message to var. + dependingVarPosInMessage.add(bindings.get((Variable) var).getKey()); // The position of the replaced variable in the message. } } if (!(pathParam instanceof Constant)) { pathParam = ((Term) pathParam).reduce(); } - dstParams.set(i, pathParam); + dstParams.set(i, pathParam); // Replace a path parameter with the substituted term. } } return filledResourcePath; } + private Set getPossitionsInMessageThatChannelMemberDependsOn(ResourcePath resourcePath, Expression messageTerm) { + Set dependingVarPosInMessage = new HashSet<>(); + Map messageVars = messageTerm.getVariables(); + for (Expression pathParam: resourcePath.getPathParams()) { + if (pathParam instanceof Variable) { + for (Entry messageVarEnt: messageVars.entrySet()) { + Variable var = messageVarEnt.getValue(); + Position varPos = messageVarEnt.getKey(); + if (pathParam.equals(var)) { + dependingVarPosInMessage.add(varPos); + } + } + } else if (pathParam instanceof Term) { + Map pathParamVars = ((Term) pathParam).getVariables(); + for (Entry messageVarEnt: messageVars.entrySet()) { + Variable var = messageVarEnt.getValue(); + Position varPos = messageVarEnt.getKey(); + if (pathParamVars.values().contains(var)) { + dependingVarPosInMessage.add(varPos); + } + } + } + } + return dependingVarPosInMessage; + } + @Override public String toString() { String channelSource = "channel " + getChannelName() + " {\n"; diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 126b47b..c1f3d2e 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -332,6 +332,9 @@ } else { exp = new Constant(symbolName, DataTransferModel.typeInt); } + } else if (symbolName.startsWith("\"") && symbolName.endsWith("\"")) { + // a string value + exp = new Constant(symbolName, DataTransferModel.typeString); } else { // a variable exp = parseVariable(stream, model, symbolName); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java new file mode 100644 index 0000000..e90a610 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -0,0 +1,129 @@ +package simulator; + +import java.util.Map; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.DataTransferChannel; + +public class ChannelState { + private DataTransferChannel channel; + private ReferenceStructure referenceStructure; + + public ChannelState(DataTransferChannel channel) { + this.channel = channel; + } + + public DataTransferChannel getChannel() { + return channel; + } + + public Map getDependingParamAndValues(List channelValues) { + if (referenceStructure == null) { + return null; + } + return referenceStructure.getDependingParamAndValues(channelValues); + } + + public List> getDependedChannelSelectorValues(Expression dependingVariable, Expression itsValue) { + if (referenceStructure == null) { + return null; + } + Map dependingVarToVal = new HashMap<>(); + dependingVarToVal.put(dependingVariable, itsValue); + return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal); + } + + public List> getDependedChannelSelectorValues(Map dependingVarToVal) { + if (referenceStructure == null) { + return null; + } + return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal); + } + + public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { + referenceStructure.addDependingParamAndValue(channelValues, dependingVariable, itsValue); + } + + private static class ReferenceStructure { + private Map dependingParamAndValues = null; + private Map referenceStructure; + + public Map getDependentParamAndValues() { + return dependingParamAndValues; + } + + public Map getDependingParamAndValues(List channelValues) { + ReferenceStructure subStructure = this; + for (Constant chVal: channelValues) { + if (subStructure.getDependentParamAndValues() == null) { + subStructure = subStructure.getReferenceStructure(chVal); + } else { + return null; + } + } + return subStructure.getDependentParamAndValues(); + } + + public List> getDependedChannelSelectorValues(Map dependingVarToVal) { + List> channelValuesList = new ArrayList<>(); + if (dependingParamAndValues != null) { + boolean isMatch = true; + for (Expression dependingVariable: dependingVarToVal.keySet()) { + if (dependingParamAndValues.keySet().contains(dependingVariable)) { + if (!dependingParamAndValues.get(dependingVariable).equals(dependingVarToVal.get(dependingVariable))) { + isMatch = false; + } + } + } + if (isMatch) { + return new ArrayList<>(); + } else { + return null; + } + } else { + for (Constant chVal: referenceStructure.keySet()) { + List> chValsList = referenceStructure.get(chVal).getDependedChannelSelectorValues(dependingVarToVal); + if (chValsList != null) { + for (List chVals: chValsList) { + chVals.add(0, chVal); + channelValuesList.add(chVals); + } + } + } + } + return channelValuesList; + } + + public void addDependingParamAndValue(Expression dependingVariable, Expression itsValue) { + if (dependingParamAndValues == null) { + dependingParamAndValues = new HashMap<>(); + } + dependingParamAndValues.put(dependingVariable, itsValue); + } + + public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { + ReferenceStructure subStructure = this; + for (Constant chVal: channelValues) { + if (subStructure.referenceStructure == null) { + subStructure.referenceStructure = new HashMap<>(); + } + ReferenceStructure nextStructure = subStructure.referenceStructure.get(chVal); + if (nextStructure == null) { + nextStructure = new ReferenceStructure(); + subStructure.referenceStructure.put(chVal, nextStructure); + } + subStructure = nextStructure; + } + subStructure.addDependingParamAndValue(dependingVariable, itsValue); + } + + public ReferenceStructure getReferenceStructure(Constant channelParam) { + return referenceStructure.get(channelParam); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index 84fe389..1a8421c 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -1,11 +1,14 @@ package simulator; import java.util.AbstractMap; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import models.algebra.Constant; import models.algebra.Expression; import models.dataConstraintModel.Channel; import models.dataConstraintModel.ResourcePath; @@ -15,90 +18,87 @@ public class Event { private DataTransferChannel channel; private Expression message; - private List channelParameters; - private Set inputResources; - private Set outputResources; - private Map> channelSelectorToInputResource = new HashMap<>(); - private Map> channelSelectorToOutputResource = new HashMap<>(); + private boolean isInput = false; + private ResourcePath inputResourcePath = null; - public Event(DataTransferChannel channel, Expression message, Resource outputResource) { + private List> channelSelectorAndValues = new ArrayList<>(); + private Map dependingParameters = new HashMap<>(); + private Set inputResources = new HashSet<>(); + private Set outputResources = new HashSet<>(); + private Set succEvents = new HashSet<>(); + private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); + private Map> channelSelectorToOutputResourcePathParam = new HashMap<>(); + + public Event(DataTransferChannel channel, Expression message, ResourcePath outputResPath, Resource outputResource) { this.channel = channel; this.message = message; + this.isInput = true; this.outputResources.add(outputResource); - connectChannelAndPathParameters(); + connectChannelSelectorAndPathParameters(); // Extract channel parameters from the output resource. List channelSelectors = channel.getAllSelectors(); - ResourcePath outputResPath = null; - for (int i = 0; i < channelSelectors.size(); i++) { - Selector sel = channelSelectors.get(i); - if (outputResPath == null) { - for (ResourcePath resPath: channel.getOutputResources()) { - if (resPath.getPathParams().contains(sel.getExpression())) { - outputResPath = resPath; // target output resource. - break; - } +// Set outputResPathSet = null; +// for (Selector sel: channelSelectors) { +// if (outputResPathSet == null) { +// outputResPathSet = channelSelectorToOutputResourcePathParam.get(sel).keySet(); +// } else { +// outputResPathSet.retainAll(channelSelectorToOutputResourcePathParam.get(sel).keySet()); +// } +// } + for (Selector sel: channelSelectors) { + int paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); + Resource ancestor = outputResource; + int idx = outputResPath.getPathParams().size(); + while (ancestor != null) { + if (ancestor.getResourceHierarchy().getNumParameters() > 0) { + idx--; + if (idx == paramIdx) break; } + ancestor = ancestor.getParent(); } - if (outputResPath != null) { - int paramIdx = channelSelectorToOutputResource.get(i).get(outputResPath); - Resource ancestor = outputResource; - while (ancestor != null) { - if (ancestor.getResourceHierarchy().getNumParameters() > 0) { - paramIdx++; - if (paramIdx == outputResPath.getPathParams().size()) break; - } - ancestor = ancestor.getParent(); - } - channelParameters.add(ancestor.getParameter()); - } + channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); } } - public Event(DataTransferChannel channel, Resource inputResource) { + public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource) { this.channel = channel; + this.isInput = false; + this.inputResourcePath = inputResPath; this.inputResources.add(inputResource); - connectChannelAndPathParameters(); + connectChannelSelectorAndPathParameters(); // Extract channel parameters from the input resource. List channelSelectors = channel.getAllSelectors(); - ResourcePath inputResPath = null; - for (int i = 0; i < channelSelectors.size(); i++) { - Selector sel = channelSelectors.get(i); - if (inputResPath == null) { - for (ResourcePath resPath: channel.getInputResources()) { - if (resPath.getPathParams().contains(sel.getExpression())) { - inputResPath = resPath; // target input resource. - break; - } - } - } + for (Selector sel: channelSelectors) { if (inputResPath != null) { - int paramIdx = channelSelectorToInputResource.get(i).get(inputResPath); - Resource ancestor = inputResource; - while (ancestor != null) { - if (ancestor.getResourceHierarchy().getNumParameters() > 0) { - paramIdx++; - if (paramIdx == inputResPath.getPathParams().size()) break; + Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + if (paramIdx != null) { + Resource ancestor = inputResource; + int idx = inputResPath.getPathParams().size(); + while (ancestor != null) { + if (ancestor.getResourceHierarchy().getNumParameters() > 0) { + idx--; + if (idx == paramIdx) break; + } + ancestor = ancestor.getParent(); } - ancestor = ancestor.getParent(); + channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); } - channelParameters.add(ancestor.getParameter()); } } } - private void connectChannelAndPathParameters() { + private void connectChannelSelectorAndPathParameters() { List channelSelectors = channel.getAllSelectors(); - for (int i = 0; i < channelSelectors.size(); i++) { - Selector sel = channelSelectors.get(i); + for (Selector sel: channelSelectors) { for (ResourcePath resPath: channel.getInputResources()) { int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); if (paramIdx >= 0) { - Map pathToIdx = channelSelectorToInputResource.get(i); + Map pathToIdx = channelSelectorToInputResourcePathParam.get(sel); if (pathToIdx == null) { pathToIdx = new HashMap<>(); - channelSelectorToInputResource.put(i, pathToIdx); + channelSelectorToInputResourcePathParam.put(sel, pathToIdx); } pathToIdx.put(resPath, paramIdx); } @@ -106,18 +106,18 @@ for (ResourcePath resPath: channel.getOutputResources()) { int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); if (paramIdx >= 0) { - Map pathToIdx = channelSelectorToOutputResource.get(i); + Map pathToIdx = channelSelectorToOutputResourcePathParam.get(sel); if (pathToIdx == null) { pathToIdx = new HashMap<>(); - channelSelectorToOutputResource.put(i, pathToIdx); + channelSelectorToOutputResourcePathParam.put(sel, pathToIdx); } pathToIdx.put(resPath, paramIdx); } } } } - - public Channel getChannel() { + + public DataTransferChannel getChannel() { return channel; } @@ -129,6 +129,42 @@ this.message = message; } + public boolean isInput() { + return isInput; + } + + public List> getChannelSelectorAndValues() { + return channelSelectorAndValues; + } + + public List getChannelSelectorValues() { + List channelValues = new ArrayList<>(); + for (Map.Entry chEnt: channelSelectorAndValues) { + channelValues.add(chEnt.getValue()); + } + return channelValues; + } + + public void updateChannelSelectorValues(List channelSelectorValues) { + for (int i = 0; i < channelSelectorValues.size(); i++) { + Map.Entry chEnt = channelSelectorAndValues.get(i); + chEnt.setValue(channelSelectorValues.get(i)); + } + } + + public void updateDependingParameter(Expression variable, Expression value) { + dependingParameters.put(variable, value); + } + + public void updateAllDependingParameters(ChannelState channelState) { + if (channelState == null) return; + dependingParameters.putAll(channelState.getDependingParamAndValues(getChannelSelectorValues())); + } + + public ResourcePath getInputResourcePath() { + return inputResourcePath; + } + public Set getInputResources() { return inputResources; } @@ -136,4 +172,44 @@ public Set getOutputResources() { return outputResources; } + + public Set getSuccessors() { + return succEvents; + } + + public void addSuccessor(Event succEvt) { + succEvents.add(succEvt); + } + + public ResourceIdentifier getInputResourceIdentifier(ResourcePath inputResPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(inputResPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + int paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + for (Expression var: dependingParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependingParameters.get(var)); + } + } + return resId; + } + + public ResourceIdentifier getOutputResourceIdentifier(ResourcePath outputResPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(outputResPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + int paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + for (Expression var: dependingParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependingParameters.get(var)); + } + } + return resId; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index 7efc83f..4d46793 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -71,19 +71,19 @@ return resourceHierarchy; } - public ResourcePath getResourcePath() { - ResourcePath resPath = null; + public ResourceIdentifier getResourceIdentifier() { + ResourceIdentifier resId = null; if (parent != null) { - ResourcePath parentResPath = parent.getResourcePath(); + ResourceIdentifier parentResId = parent.getResourceIdentifier(); if (resourceHierarchy.getNumParameters() == 0) { - resPath = new ResourcePath(parentResPath, resourceHierarchy.getResourceName(), resourceHierarchy); + resId = new ResourceIdentifier(parentResId, resourceHierarchy.getResourceName(), resourceHierarchy); } else { - resPath = new ResourcePath(parentResPath, parameter.toString(), resourceHierarchy); + resId = new ResourceIdentifier(parentResId, parameter, resourceHierarchy); } } else { - resPath = new ResourcePath(resourceHierarchy.getResourceName(), resourceHierarchy); + resId = new ResourceIdentifier(resourceHierarchy.getResourceName(), resourceHierarchy); } - return resPath; + return resId; } public ResourceState getState() { @@ -105,18 +105,38 @@ for (Map.Entry childEnt: childStates.entrySet()) { String childParam = childEnt.getKey(); ResourceState childState = childEnt.getValue(); - Type childType = childRes.getResourceStateType(); - if (DataConstraintModel.typeList.isAncestorOf(childType)) { + Type thisType = resourceHierarchy.getResourceStateType(); + if (DataConstraintModel.typeList.isAncestorOf(thisType)) { children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeInt), childState)); - } else if (DataConstraintModel.typeMap.isAncestorOf(childType)) { + } else if (DataConstraintModel.typeMap.isAncestorOf(thisType)) { children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); } } } else { // Json type. + if (this.children == null) { + for (Map.Entry childEnt: childStates.entrySet()) { + String childParam = childEnt.getKey(); + ResourceState childState = childEnt.getValue(); + Type thisType = resourceHierarchy.getResourceStateType(); + if (DataConstraintModel.typeJson.isAncestorOf(thisType)) { + children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); + } + } + this.children = children; + } return this.children; } } return children; } + + public Resource getDescendant(ResourceIdentifier resId) { + if (this.getResourceIdentifier().equals(resId)) return this; + for (Resource child: getChildren()) { + Resource res = child.getDescendant(resId); + if (res != null) return res; + } + return null; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java new file mode 100644 index 0000000..c783704 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java @@ -0,0 +1,97 @@ +package simulator; + +import java.util.HashMap; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; + +public class ResourceIdentifier extends ResourcePath { + + public ResourceIdentifier(String resourceName, ResourceHierarchy resourceHierarchy) { + super(resourceName, resourceHierarchy); + } + + public ResourceIdentifier(ResourceIdentifier parentResId, String resourceName, ResourceHierarchy resourceHierarchy) { + super(parentResId, resourceName, resourceHierarchy); + } + + public ResourceIdentifier(ResourceIdentifier parentResId, Expression exp, ResourceHierarchy resourceHierarchy) { + super(parentResId, exp, resourceHierarchy); + } + + public void setPathParam(int paramIdx, Constant param) { + pathParams.set(paramIdx, param); + } + + public boolean equals(ResourceIdentifier another) { + if (!this.getResourceHierarchy().equals(another.getResourceHierarchy())) return false; + ResourceIdentifier resId = this; + while (resId != null && another != null) { + if (resId.getResourceHierarchy().getNumParameters() == 0) { + if (!another.getResourceHierarchy().getResourceName().equals(resId.getResourceHierarchy().getResourceName())) { + return false; + } + } else { + if (!another.getLastParam().equals(resId.getLastParam())) { + return false; + } + } + resId = (ResourceIdentifier) resId.getParent(); + another = (ResourceIdentifier) another.getParent(); + } + return true; + } + + public boolean isInstanceOf(ResourcePath resPath) { + ResourcePath resId = this; + while (resId != null && resPath != null) { + if (resId.getResourceHierarchy().getNumParameters() == 0) { + if (!resPath.getResourceHierarchy().getResourceName().equals(resId.getResourceHierarchy().getResourceName())) { + return false; + } + } + resId = resId.getParent(); + resPath = resPath.getParent(); + } + return true; + } + + public Map extractParameters(ResourcePath resPath) { + ResourcePath resId = this; + Map paramMap = new HashMap<>(); + while (resId != null && resPath != null) { + if (resId.getResourceHierarchy().getNumParameters() > 0) { + paramMap.put(resPath.getLastParam(), (Constant) resId.getLastParam()); + } else { + if (!resPath.getName().equals(resId.getName())) { + return null; + } + } + resId = resId.getParent(); + resPath = resPath.getParent(); + } + return paramMap; + } + + public static ResourceIdentifier createFrom(ResourcePath resPath) { + ResourceIdentifier parent = null; + if (resPath.getParent() != null) { + parent = createFrom(resPath.getParent()); + } + ResourceHierarchy res = resPath.getResourceHierarchy(); + if (res.getNumParameters() == 0) { + if (parent == null) { + return new ResourceIdentifier(resPath.getResourceName(), res); + } else { + return new ResourceIdentifier(parent, resPath.getResourceName(), res); + } + } else { + return new ResourceIdentifier(parent, resPath.getLastParam(), res); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 0ad9b60..b3f1b61 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -1,13 +1,29 @@ package simulator; +import java.util.AbstractMap; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import models.algebra.Constant; import models.algebra.Expression; -import models.algebra.Parameter; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; public class Simulator { @@ -23,9 +39,13 @@ curState = new SystemState(); for (ResourceHierarchy res: model.getResourceHierarchies()) { if (res.getParent() == null) { + // root resource curState.addResource(new Resource(res)); } } + for (Channel channel: model.getChannels()) { + curState.addChannel((DataTransferChannel) channel); + } return curState; } @@ -33,11 +53,211 @@ return curState; } - public SystemState transition(Event inputEvent) { - SystemState nextState = new SystemState(curState); - nextState.addEvent(inputEvent); + /** + * Change the state of the system for a given input event. + * + * @param inputEvent an input event + * @return the next system state + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public SystemState transition(Event inputEvent) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + SystemState nextSystemState = new SystemState(curState); + nextSystemState.addEvent(inputEvent); - curState = nextState; - return nextState; + fireEvent(inputEvent, curState, nextSystemState); + + curState = nextSystemState; + return nextSystemState; + } + + /** + * Fire an given event and construct the next system state from the current system state. + * + * @param event an event + * @param curSystemState the current state of the system + * @param nextSystemState the next state of the system to be constructed + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + private void fireEvent(final Event event, final SystemState curSystemState, final SystemState nextSystemState) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = event.getInputResourceIdentifier(target.getResource()); + return curSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = event.getInputResourceIdentifier(target.getResource()); + return nextSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + ResourceIdentifier resId = event.getInputResourceIdentifier(target); + return curSystemState.getResource(resId).getState().getValue(); + } + }; + + DataTransferChannel channel = event.getChannel(); + if (channel.getOutputResources().size() > 0) { + // For each output resource, calculate the next state. + for (ChannelMember out: channel.getOutputChannelMembers()) { + Expression nextResState = null; + if (!event.isInput()) { + nextResState = channel.deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); + } else { + nextResState = channel.deriveUpdateExpressionOf(out, (Term) event.getMessage(), resouceStateAccessor); + } + ResourceIdentifier outResId = event.getOutputResourceIdentifier(out.getResource()); + if (nextResState instanceof Term) { + nextResState = ((Term) nextResState).reduce(); + } + ResourceIdentifier updatedOutResId = nextSystemState.updateResourceState(outResId, nextResState); + while (updatedOutResId != null) { // In addition to the target state, also its descendants' states are changed. + for (Event nextEvent: getNextEvents(updatedOutResId, curSystemState, nextSystemState)) { + fireEvent(nextEvent, curSystemState, nextSystemState); + } + updatedOutResId = (ResourceIdentifier) updatedOutResId.getParent(); + } + } + } + } + + private Set getNextEvents(ResourceIdentifier inResId, final SystemState curSystemState, final SystemState nextSystemState) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + Set nextEvents = new HashSet<>(); + for (Map.Entry chEntry: nextSystemState.getChannelStates().entrySet()) { + DataTransferChannel channel = chEntry.getKey(); + ChannelState nextChState = chEntry.getValue(); + for (ResourcePath inResPath: channel.getInputResources()) { + if (inResId.isInstanceOf(inResPath)) { + // Update the channel state and resource identifiers by the update of the input resource. + Map> dependency = channel.getMemberDependency(); + Map> invDependency = new HashMap<>(); + for (ChannelMember dependingMem: dependency.keySet()) { + for (ChannelMember dependedMem: dependency.get(dependingMem)) { + Set dependings = invDependency.get(dependedMem); + if (dependings == null) { + dependings = new HashSet<>(); + invDependency.put(dependedMem, dependings); + } + dependings.add(dependingMem); + } + } + for (ChannelMember dependedMem: invDependency.keySet()) { + if (inResPath == dependedMem.getResource()) { + // If some depending resources are to be updated by the update of an depended input resource. + final Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); + IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = nextEvent.getInputResourceIdentifier(target.getResource()); + return curSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = nextEvent.getInputResourceIdentifier(target.getResource()); + return nextSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + ResourceIdentifier resId = nextEvent.getInputResourceIdentifier(target); + return curSystemState.getResource(resId).getState().getValue(); + } + }; + Map>> filledResPaths = channel.fillOutsideResourcePaths(channel.getOutputChannelMembers().iterator().next(), resouceStateAccessor); + for (ChannelMember dependingMem: invDependency.get(dependedMem)) { + ResourcePath filledResPath = filledResPaths.get(dependingMem).getKey(); + ResourcePath unfilledResPath = dependingMem.getResource(); + for (int i = 0; i < unfilledResPath.getPathParams().size(); i++) { + Expression var = unfilledResPath.getPathParams().get(i); + Expression val = filledResPath.getPathParams().get(i); + boolean isSelector = false; + for (Selector sel: channel.getAllSelectors()) { + if (sel.getExpression().equals(var)) { + isSelector = true; + break; + } + } + if (!isSelector) { + // A selector is not a depending channel parameter. + nextChState.addDependingParamAndValue(nextEvent.getChannelSelectorValues(), var, val); + } + } + } + nextSystemState.updateChannelState(channel, nextChState); + nextEvent.updateAllDependingParameters(nextChState); + nextEvents.add(nextEvent); + } + } + if (nextChState != null) { + for (ChannelMember dependingMem: dependency.keySet()) { + if (inResPath == dependingMem.getResource()) { + // If a depending resource is directly updated. + ResourcePath filledResPath = inResId; + ResourcePath unfilledResPath = inResPath; + Map selectorVarToVal = new HashMap<>(); + Map dependingVarToVal = new HashMap<>(); + for (int i = 0; i < unfilledResPath.getPathParams().size(); i++) { + Expression var = unfilledResPath.getPathParams().get(i); + Expression val = filledResPath.getPathParams().get(i); + boolean isSelector = false; + for (Selector sel: channel.getAllSelectors()) { + if (sel.getExpression().equals(var)) { + isSelector = true; + break; + } + } + if (isSelector) { + selectorVarToVal.put(var, val); + } else { + dependingVarToVal.put(var, val); + } + } + for (List channelSelectorValues: nextChState.getDependedChannelSelectorValues(dependingVarToVal)) { + // Guess every tuple of channel selector values that may affects the updated resource. + boolean isMatch = true; + for (Expression var: selectorVarToVal.keySet()) { + for (int i = 0; i < channel.getAllSelectors().size(); i++) { + if (channel.getAllSelectors().get(i).getExpression().equals(var)) { + if (!channelSelectorValues.get(i).equals(selectorVarToVal.get(var))) { + // If the value of a selector in the updated resource path does not matches a guessed channel selector value. + isMatch = false; + } + } + } + } + if (isMatch) { + Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); + nextEvent.updateChannelSelectorValues(channelSelectorValues); + } + } + } + } + } +// ChannelState channelState = chEntry.getValue(); +// List> chValuesList = channelState.getDependedChannelValues(null, null); +// if (chValuesList != null) { +// Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); +// nextEvent.updateAllDependingParameters(channelState); +// nextEvents.add(nextEvent); +// } + } + } + } + return nextEvents; } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 7461e67..bec0132 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -1,12 +1,28 @@ package simulator; +import java.util.AbstractMap; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataFlowModel.DataTransferChannel; +import simulator.states.JsonResourceState; +import simulator.states.ListResourceState; +import simulator.states.MapResourceState; +import simulator.states.PrimitiveResourceState; +import simulator.states.ResourceState; + public class SystemState { private Set rootResources = new HashSet<>(); + private Map channelStates = new HashMap<>(); private List events = new ArrayList<>(); public SystemState() { @@ -14,6 +30,7 @@ public SystemState(SystemState prevState) { rootResources = new HashSet<>(prevState.getRootResources()); + channelStates = new HashMap<>(prevState.getChannelStates()); } public Set getRootResources() { @@ -24,6 +41,176 @@ rootResources.add(rootResource); } + public Resource getResource(ResourceIdentifier resourceIdentifier) { + for (Resource root: rootResources) { + Resource descendant = root.getDescendant(resourceIdentifier); + if (descendant != null) return descendant; + } + return null; + } + + public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + Type resType = resourceIdentifier.getResourceStateType(); + if (DataConstraintModel.typeList.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term listValue = (Term) resStateValue; + if (listValue.getSymbol().equals(DataConstraintModel.append)) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + ((ListResourceState) state).addChildState(childInfo.getKey()); + return childInfo.getValue(); + } + } + } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term mapValue = (Term) resStateValue; + if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { + Expression childExp = mapValue.getChild(1); + if (childExp instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + ((MapResourceState) state).addChildState(childId, childInfo.getKey()); + return childInfo.getValue(); + } + } + } + } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term jsonValue = (Term) resStateValue; + if (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { + Expression childExp = jsonValue.getChild(1); + if (childExp instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + ((JsonResourceState) state).addChildState(childId, childInfo.getKey()); + return childInfo.getValue(); + } + } + } + } else { + if (resStateValue instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = null; + if (res != null) { + state = res.getState(); + ((PrimitiveResourceState) state).setValue((Constant) resStateValue); + } else { + state = new PrimitiveResourceState((Constant) resStateValue); + } + return resourceIdentifier; + } + } + return resourceIdentifier; + } + + public Map.Entry createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + Type resType = null; + if (resStateValue instanceof Term) { + resType = ((Term) resStateValue).getType(); + } + if (resType != null) { + if (DataConstraintModel.typeList.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term listValue = (Term) resStateValue; + if (listValue.getSymbol().equals(DataConstraintModel.append)) { + ListResourceState state = new ListResourceState(); + Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + state.addChildState(childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term mapValue = (Term) resStateValue; + if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { + Expression childExp = mapValue.getChild(1); + if (childExp instanceof Constant) { + MapResourceState state = new MapResourceState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + state.addChildState(childId, childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } + } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term jsonValue = (Term) resStateValue; + if (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { + Expression childExp = jsonValue.getChild(1); + if (childExp instanceof Constant) { + JsonResourceState state = new JsonResourceState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + ((Constant) childExp).getSymbol().getName(), + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + state.addChildState(childId, childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } + } else { + if (resStateValue instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = null; + if (res != null) { + state = res.getState(); + ((PrimitiveResourceState) state).setValue((Constant) resStateValue); + } else { + state = new PrimitiveResourceState((Constant) resStateValue); + } + return new AbstractMap.SimpleEntry<>(state, resourceIdentifier); + } + } + } + return null; + } + + public Map getChannelStates() { + return channelStates; + } + + public ChannelState getChannelState(DataTransferChannel channel) { + return channelStates.get(channel); + } + + public void addChannel(DataTransferChannel channel) { + channelStates.put(channel, null); + } + + public void updateChannelState(DataTransferChannel channel, ChannelState channelState) { + channelStates.put(channel, channelState); + } + public List getEvents() { return events; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java index 1e6804d..6ad1362 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java @@ -13,6 +13,10 @@ public Constant getValue() { return value; } + + public void setValue(Constant newValue) { + value = newValue; + } @Override boolean hasChildren() { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java deleted file mode 100644 index ffbef05..0000000 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package tests; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import models.*; -import models.algebra.Variable; -import models.dataConstraintModel.*; -import models.dataFlowModel.*; - -public class DataFlowModelTest { - - @Test - public void test() { - // Construct a data-flow architecture model. - DataTransferModel model = new DataTransferModel(); - - ResourcePath customers = new ResourcePath("customers"); // "customers" - ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" - ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" - ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" - ResourcePath companies = new ResourcePath("companies"); // "companies" - ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" - ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" - model.addResourcePath(customer_off); - model.addResourcePath(customer_add); - model.addResourcePath(company_add); - - // === cio_setCustomerOff(uid) === - // - // out customers.{uid}.off(c, set(x)) == x - // - DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office (an input channel) - ChannelMember customer_off_1 = new ChannelMember(customer_off); - cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); - assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); - - // === cio_setCompanyAdd(cid) === - // - // out companies.{cid}.add(a, set(y)) == y - // - DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address (an input channel) - ChannelMember company_add_1 = new ChannelMember(company_add); - cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); - assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); - - // === c === - // - // in customers.{uid}.off( c, update(cid, a2)) == cid - // in companies.{cid}.add( a, update(cid, a2)) == a2 - // out customers.{uid}.add(b, update(cid, a2)) == a2 - // - DataTransferChannel c = new DataTransferChannel("c", new Variable("uid")); // update customer's address - ChannelMember customer_off_2 = new ChannelMember(customer_off); - ChannelMember company_add_2 = new ChannelMember(company_add); - ChannelMember customer_add_2 = new ChannelMember(customer_add); - c.addChannelMemberAsInput(customer_off_2); - c.addChannelMemberAsInput(company_add_2); - c.addChannelMemberAsOutput(customer_add_2); - assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); - assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); - assertEquals(company_add.getPathParams().get(0), new Variable("cid")); - - // Construct a data-flow architecture model. - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); - model.addChannel(c); - - // Check the model. - assertEquals(3, model.getResourcePaths().size()); - assertEquals(7, model.getResourceHierarchies().size()); - assertEquals(2, model.getIOChannels().size()); - assertEquals(1, model.getChannels().size()); - - // Extract the resource dependency graph. - DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); - - // Check the graph. - assertEquals(7, resourceDependencyGraph.getResourceNodes().size()); - assertEquals(3, resourceDependencyGraph.getChannelNodes().size()); - assertEquals(5, resourceDependencyGraph.getEdges().size()); - for (Edge e: resourceDependencyGraph.getEdges()) { - System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java new file mode 100644 index 0000000..c0f38af --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java @@ -0,0 +1,88 @@ +package tests; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import models.*; +import models.algebra.Variable; +import models.dataConstraintModel.*; +import models.dataFlowModel.*; + +public class DataTransferModelTest { + + @Test + public void test() { + // Construct a data-flow architecture model. + DataTransferModel model = new DataTransferModel(); + + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + model.addResourcePath(customer_off); + model.addResourcePath(customer_add); + model.addResourcePath(company_add); + + // === cio_setCustomerOff(uid) === + // + // out customers.{uid}.off(c, set(x)) == x + // + DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office (an input channel) + ChannelMember customer_off_1 = new ChannelMember(customer_off); + cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); + assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); + + // === cio_setCompanyAdd(cid) === + // + // out companies.{cid}.add(a, set(y)) == y + // + DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address (an input channel) + ChannelMember company_add_1 = new ChannelMember(company_add); + cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); + assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); + + // === c === + // + // in customers.{uid}.off( c, update(cid, a2)) == cid + // in companies.{cid}.add( a, update(cid, a2)) == a2 + // out customers.{uid}.add(b, update(cid, a2)) == a2 + // + DataTransferChannel c = new DataTransferChannel("c", new Variable("uid")); // update customer's address + ChannelMember customer_off_2 = new ChannelMember(customer_off); + ChannelMember company_add_2 = new ChannelMember(company_add); + ChannelMember customer_add_2 = new ChannelMember(customer_add); + c.addChannelMemberAsInput(customer_off_2); + c.addChannelMemberAsInput(company_add_2); + c.addChannelMemberAsOutput(customer_add_2); + assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(company_add.getPathParams().get(0), new Variable("cid")); + + // Construct a data-flow architecture model. + model.addIOChannel(cio_setCustomerOff); + model.addIOChannel(cio_setCompanyAdd); + model.addChannel(c); + + // Check the model. + assertEquals(3, model.getResourcePaths().size()); + assertEquals(7, model.getResourceHierarchies().size()); + assertEquals(2, model.getIOChannels().size()); + assertEquals(1, model.getChannels().size()); + + // Extract the resource dependency graph. + DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); + + // Check the graph. + assertEquals(7, resourceDependencyGraph.getResourceNodes().size()); + assertEquals(3, resourceDependencyGraph.getChannelNodes().size()); + assertEquals(5, resourceDependencyGraph.getEdges().size()); + for (Edge e: resourceDependencyGraph.getEdges()) { + System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java index 76613ec..5ec6984 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java @@ -5,64 +5,152 @@ import org.junit.Test; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; import models.algebra.Variable; import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import simulator.Event; import simulator.Resource; import simulator.Simulator; import simulator.SystemState; +import simulator.ResourceIdentifier; import simulator.states.MapResourceState; public class SimulatorTest { @Test public void test() { - // Construct a data transfer architecture model. - DataTransferModel model = new DataTransferModel(); + try { + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + // Construct a data transfer architecture model. + DataTransferModel model = new DataTransferModel(); + + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, + new Variable("uid", DataConstraintModel.typeString)); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, + new Variable("cid", DataConstraintModel.typeString)); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + model.addResourcePath(customer_off); + model.addResourcePath(customer_add); + model.addResourcePath(company_add); + model.addResourcePath(customers); + model.addResourcePath(companies); + + // For channel CIO_AddCustomer + DataTransferChannel cio_addCustomer = new DataTransferChannel("CIO_AddCustomer"); // add a customer + ChannelMember customers1 = new ChannelMember(customers); + cio_addCustomer.addChannelMemberAsOutput(customers1); + + // For channel CIO_AddCompany + DataTransferChannel cio_addCompany = new DataTransferChannel("CIO_AddCompany"); // add a company + ChannelMember companies1 = new ChannelMember(companies); + stream.addLine("db:Map"); + Expression curStateExp = parser.parseTerm(stream, model); + companies1.getStateTransition().setCurStateExpression(curStateExp); + stream.addLine("addCampany(cid:Str, add:Str)"); + Expression messageExp = parser.parseTerm(stream, model); + companies1.getStateTransition().setMessageExpression(messageExp); + stream.addLine("insert(db, cid, {\"add\": add})"); + Expression nextStateExp = parser.parseTerm(stream, model); + companies1.getStateTransition().setNextStateExpression(nextStateExp); + cio_addCompany.addChannelMemberAsOutput(companies1); + + // For channel CIO_SetCustomerOff + DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office + ChannelMember customer_off_1 = new ChannelMember(customer_off); + cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); + + // For channel CIO_SetCompanyAdd + DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address + ChannelMember company_add_1 = new ChannelMember(company_add); + cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); + + // For channel C + DataTransferChannel c = new DataTransferChannel("C", new Variable("uid")); // update customer's address + ChannelMember customer_off_2 = new ChannelMember(customer_off); + stream.addLine("cid:Str"); + Expression curStateExp2 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setCurStateExpression(curStateExp2); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp2 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setMessageExpression(messageExp2); + stream.addLine("cid2"); + Expression nextStateExp2 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setNextStateExpression(nextStateExp2); + c.addChannelMemberAsInput(customer_off_2); + + ChannelMember company_add_2 = new ChannelMember(company_add); + stream.addLine("a1:Str"); + Expression curStateExp3 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setCurStateExpression(curStateExp3); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp3 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setMessageExpression(messageExp3); + stream.addLine("add2"); + Expression nextStateExp3 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setNextStateExpression(nextStateExp3); + c.addChannelMemberAsInput(company_add_2); + + ChannelMember customer_add_2 = new ChannelMember(customer_add); + stream.addLine("a3:Str"); + Expression curStateExp4 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setCurStateExpression(curStateExp4); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp4 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setMessageExpression(messageExp4); + stream.addLine("add2"); + Expression nextStateExp4 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setNextStateExpression(nextStateExp4); + c.addChannelMemberAsOutput(customer_add_2); + + model.addIOChannel(cio_setCustomerOff); + model.addIOChannel(cio_setCompanyAdd); + model.addChannel(c); + + Simulator simulator = new Simulator(model); + + // Initial state + SystemState initialState = simulator.init(); + assertEquals(2, initialState.getRootResources().size()); + for (Resource rootRes: initialState.getRootResources()) { + System.out.println(rootRes.getResourceHierarchy().getResourceName()); + assertTrue(rootRes.getState() instanceof MapResourceState); + assertEquals(0, rootRes.getChildren().size()); + assertEquals(0, ((MapResourceState) rootRes.getState()).getChildStates().size()); + } - ResourcePath customers = new ResourcePath("customers"); // "customers" - ResourcePath customer = new ResourcePath(customers, - new Variable("uid", DataConstraintModel.typeString)); // "customers.{uid}" - ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" - ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" - ResourcePath companies = new ResourcePath("companies"); // "companies" - ResourcePath company = new ResourcePath(companies, - new Variable("cid", DataConstraintModel.typeString)); // "companies.{cid}" - ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" - model.addResourcePath(customer_off); - model.addResourcePath(customer_add); - model.addResourcePath(company_add); - - Channel cio_setCustomerOff = new Channel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office - ChannelMember customer_off_1 = new ChannelMember(customer_off); - cio_setCustomerOff.addChannelMember(customer_off_1); - - Channel cio_setCompanyAdd = new Channel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address - ChannelMember company_add_1 = new ChannelMember(company_add); - cio_setCompanyAdd.addChannelMember(company_add_1); - - Channel c = new Channel("c", new Variable("uid")); // update customer's address - ChannelMember customer_off_2 = new ChannelMember(customer_off); - ChannelMember company_add_2 = new ChannelMember(company_add); - ChannelMember customer_add_2 = new ChannelMember(customer_add); - c.addChannelMember(customer_off_2); - c.addChannelMember(company_add_2); - c.addChannelMember(customer_add_2); - - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); - model.addChannel(c); - - Simulator simulator = new Simulator(model); - SystemState initialState = simulator.init(); - assertEquals(2, initialState.getRootResources().size()); - for (Resource rootRes: initialState.getRootResources()) { - System.out.println(rootRes.getResourceHierarchy().getResourceName()); - assertTrue(rootRes.getState() instanceof MapResourceState); - assertEquals(0, rootRes.getChildren().size()); - assertEquals(0, ((MapResourceState) rootRes.getState()).getChildStates().size()); + stream.addLine("addCompany(\"1\", \"Osaka\")"); + Expression message = parser.parseTerm(stream, model); + Event addCompany = new Event(cio_addCompany, message, companies, initialState.getResource(ResourceIdentifier.createFrom(companies))); + + // Next state + simulator.transition(addCompany); + SystemState nextState = simulator.getCurState(); + + // After the next state + + + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); } } }