diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index d21cc49..61ab485 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -414,32 +414,13 @@ // Calculate message constraints from input state transitions for (ChannelMember inputMember: getInputChannelMembers()) { - Expression curInputStateAccessor = null; - Expression nextInputStateAccessor = null; - if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputMember, targetMember); - nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputMember, targetMember); - } else { - curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); - nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); - } - Set substitutedPositionsInMessage = new HashSet<>(); - Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositionsInMessage); - if (substitutedPositionsInMessage.size() > 0) substitutedPositionsInMessageFromChannels.put(inputMember, substitutedPositionsInMessage); + Expression messageConstraintByInput = calcMessageConstraintForInputMember(inputMember, targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); messageConstraints.add((Term) messageConstraintByInput); } // Calculate message constraints from reference state transitions for (ChannelMember referenceMember: getReferenceChannelMembers()) { - Expression curInputStateAccessor = null; - if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceMember, targetMember); - } else { - curInputStateAccessor = inputResourceToStateAccessor.get(referenceMember).getCurrentStateAccessorFor(referenceMember, targetMember); - } - Set substitutedPositions = new HashSet<>(); - Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, substitutedPositions); - if (substitutedPositions.size() > 0) substitutedPositionsInMessageFromChannels.put(referenceMember, substitutedPositions); + Expression messageConstraintByReference = calcMessageConstraintForReferenceMember(referenceMember, targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); messageConstraints.add((Term) messageConstraintByReference); } @@ -457,6 +438,39 @@ } return unifiedMessage; } + + public Expression calcMessageConstraintForInputMember(ChannelMember inputMember, ChannelMember targetMember, IResourceStateAccessor stateAccessor, + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { + Expression curInputStateAccessor = null; + Expression nextInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputMember, targetMember); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); + } + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositionsInMessage); + if (substitutedPositionsInMessage.size() > 0) substitutedPositionsInMessageFromChannels.put(inputMember, substitutedPositionsInMessage); + return messageConstraintByInput; + } + + public Expression calcMessageConstraintForReferenceMember(ChannelMember referenceMember, ChannelMember targetMember, IResourceStateAccessor stateAccessor, + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { + Expression curInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceMember, targetMember); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(referenceMember).getCurrentStateAccessorFor(referenceMember, targetMember); + } + Set substitutedPositions = new HashSet<>(); + Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, substitutedPositions); + if (substitutedPositions.size() > 0) substitutedPositionsInMessageFromChannels.put(referenceMember, substitutedPositions); + return messageConstraintByReference; + } /** * Get depended channel members and their positions in the message. @@ -469,14 +483,18 @@ for (ChannelMember inputMember: getInputChannelMembers()) { Set substitutedPositionsInMessage = new HashSet<>(); Expression messageTerm = inputMember.getStateTransition().getMessageExpression(); + Expression curStateTerm = inputMember.getStateTransition().getCurStateExpression(); + Expression nextStateTerm = inputMember.getStateTransition().getNextStateExpression(); 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 (curStateTerm.getVariables().values().contains(var) || nextStateTerm.getVariables().values().contains(var)) { + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } } } } @@ -487,14 +505,18 @@ for (ChannelMember referenceMember: getReferenceChannelMembers()) { Set substitutedPositionsInMessage = new HashSet<>(); Expression messageTerm = referenceMember.getStateTransition().getMessageExpression(); + Expression curStateTerm = referenceMember.getStateTransition().getCurStateExpression(); + Expression nextStateTerm = referenceMember.getStateTransition().getNextStateExpression(); 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 (curStateTerm.getVariables().values().contains(var) || nextStateTerm.getVariables().values().contains(var)) { + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } } } } @@ -503,7 +525,7 @@ return channelMembersMessageDependsOn; } - private ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPosInMessage) + public ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPosInMessage) throws ResolvingMultipleDefinitionIsFutureWork { ResourcePath filledResourcePath = new ResourcePath(resource); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java index e90a610..1fdc906 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -46,6 +46,9 @@ } public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { + if (referenceStructure == null) { + referenceStructure = new ReferenceStructure(); + } referenceStructure.addDependingParamAndValue(channelValues, dependingVariable, itsValue); } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index 1a8421c..dcffc1a 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -10,10 +10,16 @@ import models.algebra.Constant; import models.algebra.Expression; -import models.dataConstraintModel.Channel; +import models.algebra.InvalidMessage; +import models.algebra.Position; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; public class Event { private DataTransferChannel channel; @@ -116,7 +122,7 @@ } } } - + public DataTransferChannel getChannel() { return channel; } @@ -152,13 +158,127 @@ } } - public void updateDependingParameter(Expression variable, Expression value) { - dependingParameters.put(variable, value); + public Map getDependingParameters() { + return dependingParameters; } - public void updateAllDependingParameters(ChannelState channelState) { - if (channelState == null) return; - dependingParameters.putAll(channelState.getDependingParamAndValues(getChannelSelectorValues())); + + public Term updateDependingParameters(IResourceStateValueProvider resourceStateValueProvider) { + IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = getInputResourceIdentifier(target.getResource()); + return resourceStateValueProvider.getCurrentStateValueOf(resId); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = getInputResourceIdentifier(target.getResource()); + return resourceStateValueProvider.getNextStateValueOf(resId); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + ResourceIdentifier resId = getInputResourceIdentifier(target); + return resourceStateValueProvider.getCurrentStateValueOf(resId); + } + }; + + try { + Map> substitutedPositionsInMessageFromChannels = new HashMap<>(); + Term unifiedMessage = null; + + // Calculate message constraints from leaf channel members on the channel member dependency graph. + Map> dependency = channel.getMemberDependency(); + Set toResolve = new HashSet<>(); + Set resolved = new HashSet<>(); + for (Set depended: dependency.values()) { + toResolve.addAll(depended); + } + for (ChannelMember depending: dependency.keySet()) { + toResolve.remove(depending); + } + for (ChannelMember leafMember: toResolve) { + Expression messageConstraint = null; + if (channel.getInputChannelMembers().contains(leafMember)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(leafMember)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + resolved.addAll(toResolve); + toResolve.clear(); + + for (;;) { + for (Map.Entry> dependEnt: dependency.entrySet()) { + ChannelMember dependingMem = dependEnt.getKey(); + Set dependedMems = dependEnt.getValue(); + if (!resolved.contains(dependingMem) && resolved.containsAll(dependedMems)) { + toResolve.add(dependingMem); + } + } + if (toResolve.size() == 0) break; + for (ChannelMember dependingMem: toResolve) { + // Fill the path parameters of the resource path of a depending channel member. + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = channel.fillOutsideResourcePath(dependingMem.getResource(), unifiedMessage, dependingMem.getStateTransition().getMessageExpression(), dependingVarPosInMessage); + 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 depending channel parameter + updateDependingParameter(var, val); + } + } + + // Calculate message constraint + Expression messageConstraint = null; + if (channel.getInputChannelMembers().contains(dependingMem)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(dependingMem)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + resolved.addAll(toResolve); + toResolve.clear(); + } + return unifiedMessage; + } catch (ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed e) { + e.printStackTrace(); + } + return null; + } + + public void updateDependingParameter(Expression variable, Expression value) { + dependingParameters.put(variable, value); } public ResourcePath getInputResourcePath() { @@ -181,12 +301,39 @@ succEvents.add(succEvt); } + public ResourceIdentifier getResourceIdentifier(ResourcePath resPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(resPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(resPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + } + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Integer paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(resPath); + if (paramIdx != null) { + 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 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()); + Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } } for (Expression var: dependingParameters.keySet()) { int paramIdx = resId.getPathParams().indexOf(var); @@ -201,8 +348,10 @@ 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()); + Integer paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } } for (Expression var: dependingParameters.keySet()) { int paramIdx = resId.getPathParams().indexOf(var); @@ -212,4 +361,10 @@ } return resId; } + + + public interface IResourceStateValueProvider { + Expression getCurrentStateValueOf(ResourceIdentifier resId); + Expression getNextStateValueOf(ResourceIdentifier resId); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index 4d46793..a0e8aaf 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -133,6 +133,7 @@ public Resource getDescendant(ResourceIdentifier resId) { if (this.getResourceIdentifier().equals(resId)) return this; + if (!resId.startsWith(this.getResourceIdentifier())) return null; for (Resource child: getChildren()) { Resource res = child.getDescendant(resId); if (res != null) return res; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java index c783704..e744022 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java @@ -28,7 +28,7 @@ } public boolean equals(ResourceIdentifier another) { - if (!this.getResourceHierarchy().equals(another.getResourceHierarchy())) return false; + if (!this.getResourceHierarchy().toString().equals(another.getResourceHierarchy().toString())) return false; ResourceIdentifier resId = this; while (resId != null && another != null) { if (resId.getResourceHierarchy().getNumParameters() == 0) { @@ -46,6 +46,20 @@ return true; } + public boolean startsWith(ResourceIdentifier another) { + if (this.length() > another.length()) { + return ((ResourceIdentifier) parent).startsWith(another); + } + return this.equals(another); + } + + public int length() { + if (parent == null) { + return 1; + } + return ((ResourceIdentifier) parent).length() + 1; + } + public boolean isInstanceOf(ResourcePath resPath) { ResourcePath resId = this; while (resId != null && resPath != null) { @@ -53,6 +67,8 @@ if (!resPath.getResourceHierarchy().getResourceName().equals(resId.getResourceHierarchy().getResourceName())) { return false; } + } else if (resId.getResourceHierarchy().getNumParameters() != resPath.getResourceHierarchy().getNumParameters()) { + return false; } resId = resId.getParent(); resPath = resPath.getParent(); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index b3f1b61..1987099 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -25,6 +25,7 @@ import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; +import simulator.Event.IResourceStateValueProvider; public class Simulator { private DataTransferModel model; @@ -92,20 +93,26 @@ IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { @Override public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourceIdentifier resId = event.getInputResourceIdentifier(target.getResource()); - return curSystemState.getResource(resId).getState().getValue(); + ResourceIdentifier resId = event.getResourceIdentifier(target.getResource()); + Resource res = curSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); } @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourceIdentifier resId = event.getInputResourceIdentifier(target.getResource()); - return nextSystemState.getResource(resId).getState().getValue(); + ResourceIdentifier resId = event.getResourceIdentifier(target.getResource()); + Resource res = nextSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); } @Override public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { - ResourceIdentifier resId = event.getInputResourceIdentifier(target); - return curSystemState.getResource(resId).getState().getValue(); + ResourceIdentifier resId = event.getResourceIdentifier(target); + Resource res = curSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); } }; @@ -124,7 +131,7 @@ 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. + while (updatedOutResId != null) { // In addition to the target state, its descendants' states are also changed. for (Event nextEvent: getNextEvents(updatedOutResId, curSystemState, nextSystemState)) { fireEvent(nextEvent, curSystemState, nextSystemState); } @@ -137,69 +144,48 @@ private Set getNextEvents(ResourceIdentifier inResId, final SystemState curSystemState, final SystemState nextSystemState) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { Set nextEvents = new HashSet<>(); + IResourceStateValueProvider resourceStateValueProvider = new IResourceStateValueProvider() { + @Override + public Expression getCurrentStateValueOf(ResourceIdentifier resId) { + return curSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getNextStateValueOf(ResourceIdentifier resId) { + return nextSystemState.getResource(resId).getState().getValue(); + } + }; for (Map.Entry chEntry: nextSystemState.getChannelStates().entrySet()) { DataTransferChannel channel = chEntry.getKey(); ChannelState nextChState = chEntry.getValue(); + 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 (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); - } - } + nextEvent.updateDependingParameters(resourceStateValueProvider); + if (nextChState == null) { + nextChState = new ChannelState(channel); + nextSystemState.updateChannelState(channel, nextChState); } - nextSystemState.updateChannelState(channel, nextChState); - nextEvent.updateAllDependingParameters(nextChState); + List channelSelValues = nextEvent.getChannelSelectorValues(); + for (Map.Entry paramEnt: nextEvent.getDependingParameters().entrySet()) { + nextChState.addDependingParamAndValue(channelSelValues, paramEnt.getKey(), paramEnt.getValue()); + } nextEvents.add(nextEvent); } } @@ -229,18 +215,18 @@ } for (List channelSelectorValues: nextChState.getDependedChannelSelectorValues(dependingVarToVal)) { // Guess every tuple of channel selector values that may affects the updated resource. - boolean isMatch = true; + boolean doesMatch = 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; + doesMatch = false; } } } } - if (isMatch) { + if (doesMatch) { Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); nextEvent.updateChannelSelectorValues(channelSelectorValues); } @@ -248,13 +234,6 @@ } } } -// 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); -// } } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index bec0132..04d5961 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -51,7 +51,7 @@ public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { Type resType = resourceIdentifier.getResourceStateType(); - if (DataConstraintModel.typeList.isAncestorOf(resType)) { + if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; @@ -67,7 +67,7 @@ return childInfo.getValue(); } } - } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { + } else if (resType != null && DataConstraintModel.typeMap.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { } else if (resStateValue instanceof Term) { Term mapValue = (Term) resStateValue; @@ -86,7 +86,7 @@ } } } - } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { + } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; @@ -113,7 +113,16 @@ state = res.getState(); ((PrimitiveResourceState) state).setValue((Constant) resStateValue); } else { - state = new PrimitiveResourceState((Constant) resStateValue); + ResourceIdentifier parentResId = (ResourceIdentifier) resourceIdentifier.getParent(); + Type parentResType = parentResId.getResourceStateType(); + if (parentResType != null && DataConstraintModel.typeList.isAncestorOf(parentResType)) { + } else if (parentResType != null && DataConstraintModel.typeMap.isAncestorOf(parentResType)) { + JsonResourceState parentState = (JsonResourceState) getResource(parentResId).getState(); + parentState.addChildState(((Constant) resourceIdentifier.getLastParam()).toString(), new PrimitiveResourceState((Constant) resStateValue)); + } else if (parentResType != null && DataConstraintModel.typeJson.isAncestorOf(parentResType)) { + JsonResourceState parentState = (JsonResourceState) getResource(parentResId).getState(); + parentState.addChildState("\"" + resourceIdentifier.getResourceName() + "\"", new PrimitiveResourceState((Constant) resStateValue)); + } } return resourceIdentifier; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java index 2238c1e..327da4f 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java @@ -20,6 +20,7 @@ newTerm.addChild(value); newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); newTerm.addChild(childEnt.getValue().getValue()); + value = newTerm; } return value; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java index 97de7f3..e49bd72 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java @@ -21,6 +21,7 @@ Term newTerm = new Term(DataConstraintModel.append); newTerm.addChild(value); newTerm.addChild(child.getValue()); + value = newTerm; } return value; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java index efb4cf4..1f36406 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java @@ -20,6 +20,7 @@ newTerm.addChild(value); newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); newTerm.addChild(childEnt.getValue().getValue()); + value = newTerm; } return value; } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java index 5ec6984..b6988f9 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java @@ -11,7 +11,6 @@ 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; @@ -49,29 +48,42 @@ ResourcePath company = new ResourcePath(companies, new Variable("cid", DataConstraintModel.typeString)); // "companies.{cid}" ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + ResourcePath company2 = new ResourcePath(companies, + new Variable("cid2", DataConstraintModel.typeString)); // "companies.{cid2}" + ResourcePath company2_add = new ResourcePath(company2, "add"); // "companies.{cid2}.add" model.addResourcePath(customer_off); model.addResourcePath(customer_add); model.addResourcePath(company_add); + model.addResourcePath(company2_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); + stream.addLine("db:Map"); + Expression curStateExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setCurStateExpression(curStateExp0); + stream.addLine("addCustomer(uid:Str, off:Str)"); + Expression messageExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setMessageExpression(messageExp0); + stream.addLine("insert(db, uid, {\"off\": off})"); + Expression nextStateExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setNextStateExpression(nextStateExp0); 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); + Expression curStateExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setCurStateExpression(curStateExp1); stream.addLine("addCampany(cid:Str, add:Str)"); - Expression messageExp = parser.parseTerm(stream, model); - companies1.getStateTransition().setMessageExpression(messageExp); + Expression messageExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setMessageExpression(messageExp1); stream.addLine("insert(db, cid, {\"add\": add})"); - Expression nextStateExp = parser.parseTerm(stream, model); - companies1.getStateTransition().setNextStateExpression(nextStateExp); + Expression nextStateExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setNextStateExpression(nextStateExp1); cio_addCompany.addChannelMemberAsOutput(companies1); // For channel CIO_SetCustomerOff @@ -98,7 +110,7 @@ customer_off_2.getStateTransition().setNextStateExpression(nextStateExp2); c.addChannelMemberAsInput(customer_off_2); - ChannelMember company_add_2 = new ChannelMember(company_add); + ChannelMember company_add_2 = new ChannelMember(company2_add); stream.addLine("a1:Str"); Expression curStateExp3 = parser.parseTerm(stream, model); company_add_2.getStateTransition().setCurStateExpression(curStateExp3); @@ -130,24 +142,45 @@ // 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()); } - - stream.addLine("addCompany(\"1\", \"Osaka\")"); - Expression message = parser.parseTerm(stream, model); - Event addCompany = new Event(cio_addCompany, message, companies, initialState.getResource(ResourceIdentifier.createFrom(companies))); + System.out.println("companies:" + initialState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + initialState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); // Next state + stream.addLine("addCompany(\"A\", \"Osaka\")"); + Expression messageAddComp = parser.parseTerm(stream, model); + Event addCompany = new Event(cio_addCompany, messageAddComp, companies, initialState.getResource(ResourceIdentifier.createFrom(companies))); simulator.transition(addCompany); SystemState nextState = simulator.getCurState(); - // After the next state + assertEquals(2, nextState.getRootResources().size()); + Resource companiesRes = nextState.getResource(ResourceIdentifier.createFrom(companies)); + assertTrue(companiesRes.getState() instanceof MapResourceState); + assertEquals(1, companiesRes.getChildren().size()); + assertEquals(1, ((MapResourceState) companiesRes.getState()).getChildStates().size()); + System.out.println("companies:" + nextState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + nextState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); + // After the next state + stream.addLine("addCustomer(\"1\", \"A\")"); + Expression messageAddCust = parser.parseTerm(stream, model); + Event addCustomer = new Event(cio_addCustomer, messageAddCust, customers, nextState.getResource(ResourceIdentifier.createFrom(customers))); + simulator.transition(addCustomer); + SystemState nextNextState = simulator.getCurState(); + + assertEquals(2, nextState.getRootResources().size()); + Resource customersRes = nextNextState.getResource(ResourceIdentifier.createFrom(customers)); + assertTrue(customersRes.getState() instanceof MapResourceState); + assertEquals(1, customersRes.getChildren().size()); + assertEquals(1, ((MapResourceState) customersRes.getState()).getChildStates().size()); + System.out.println("companies:" + nextNextState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + nextNextState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { e.printStackTrace();