package simulator;
import models.algebra.*;
import models.dataConstraintModel.Channel;
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;
import java.util.*;
/**
* Event occurred at a channel
*
* @author Nitta
*
*/
public class Event {
private DataTransferChannel channel;
private Expression message;
private boolean isInput = false;
private ResourcePath inputResourcePath = null;
private Resource inputResource = null;
private List<Map.Entry<Selector, Constant>> channelSelectorAndValues = new ArrayList<>();
private Map<Expression, Expression> dependingParameters = new HashMap<>();
private Set<Resource> outputResources = new HashSet<>();
private Set<Event> childEvents = new HashSet<>();
private Map<Selector, Map<ResourcePath, Map.Entry<Integer, Set<Position>>>> channelSelectorToInputOrReferenceResourcePathParam = new HashMap<>();
private Map<Selector, Map<ResourcePath, Map.Entry<Integer, Set<Position>>>> channelSelectorToOutputResourcePathParam = new HashMap<>();
/**
* Constructor for an input event channel
*
* @param channel an input event channel
* @param message an message for the channel
* @param outputResPath an output side resource path of the channel
* @param outputResource an output side resource of the channel
*/
public Event(DataTransferChannel channel, Expression message, ResourcePath outputResPath, Resource outputResource) {
this.channel = channel;
this.message = message;
this.isInput = true;
this.outputResources.add(outputResource);
connectChannelSelectorAndPathParameters();
// Extract the values of the channel selectors from the output resource.
List<Selector> channelSelectors = channel.getAllSelectors();
for (Selector sel : channelSelectors) {
Map.Entry<Integer, Set<Position>> paramIdxAndPos = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath);
Resource ancestor = outputResource;
int idx = outputResPath.getPathParams().size();
while (ancestor != null) {
if (ancestor.getResourceHierarchy().getNumParameters() > 0) {
idx--;
if (idx == paramIdxAndPos.getKey()) break;
}
ancestor = ancestor.getParent();
}
if (ancestor != null)
channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter()));
}
}
/**
* Constructor for a non-event channel
*
* @param channel a non-event channel
* @param inputResPath an input side resource path of the channel
* @param inputResource an input side resource of the channel
*/
public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource) {
this.channel = channel;
this.isInput = false;
this.inputResourcePath = inputResPath;
this.inputResource = inputResource;
connectChannelSelectorAndPathParameters();
// Extract the values of the channel selectors from the input resource.
List<Selector> channelSelectors = channel.getAllSelectors();
for (Selector sel : channelSelectors) {
if (inputResPath != null) {
Map.Entry<Integer, Set<Position>> paramIdxAndPos = channelSelectorToInputOrReferenceResourcePathParam.get(sel).get(inputResPath);
if (paramIdxAndPos != null) {
Resource ancestor = inputResource;
int idx = inputResPath.getPathParams().size();
while (ancestor != null) {
if (ancestor.getResourceHierarchy().getNumParameters() > 0) {
idx--;
if (idx == paramIdxAndPos.getKey()) break;
}
ancestor = ancestor.getParent();
}
channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter()));
}
}
}
}
/**
* Constructor for a non-event channel
*
* @param channel a non-event channel
* @param inputResPath an input side resource path of the channel
* @param inputResource an input side resource of the channel
* @param channelSelectorValues the values of depended channel selectors
* @param dependingVarToVal the values of depending channel selectors
*/
public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource, List<Constant> channelSelectorValues, Map<Expression, Expression> dependingVarToVal) {
this.channel = channel;
this.isInput = false;
this.inputResourcePath = inputResPath;
this.inputResource = inputResource;
connectChannelSelectorAndPathParameters();
// Extract the values of the channel selectors from channelSelectorValues.
List<Selector> channelSelectors = channel.getAllSelectors();
for (int i = 0; i < channelSelectors.size(); i++) {
Selector sel = channelSelectors.get(i);
channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, channelSelectorValues.get(i)));
}
this.dependingParameters = dependingVarToVal;
}
private void connectChannelSelectorAndPathParameters() {
List<Selector> channelSelectors = channel.getAllSelectors();
for (Selector sel : channelSelectors) {
Set<ResourcePath> inputAndReferenceResPaths = new HashSet<>(channel.getInputResources());
inputAndReferenceResPaths.addAll(channel.getReferenceResources());
for (ResourcePath resPath : inputAndReferenceResPaths) {
for (int paramIdx = 0; paramIdx < resPath.getPathParams().size(); paramIdx++) {
Expression pathParam = resPath.getPathParams().get(paramIdx);
if (pathParam.contains(sel.getExpression())) {
for (Map.Entry<Position, Variable> posAndVar : pathParam.getVariables().entrySet()) {
Position p = posAndVar.getKey();
Variable v = posAndVar.getValue();
if (v.equals(sel.getExpression())) {
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> pathToIdxAndPos = channelSelectorToInputOrReferenceResourcePathParam.get(sel);
if (pathToIdxAndPos == null) {
pathToIdxAndPos = new HashMap<>();
channelSelectorToInputOrReferenceResourcePathParam.put(sel, pathToIdxAndPos);
}
Map.Entry<Integer, Set<Position>> idxAndPos = pathToIdxAndPos.get(resPath);
if (idxAndPos == null) {
idxAndPos = new AbstractMap.SimpleEntry<>(paramIdx, new HashSet<>());
pathToIdxAndPos.put(resPath, idxAndPos);
}
idxAndPos.getValue().add(p);
}
}
}
}
}
for (ResourcePath resPath : channel.getOutputResources()) {
for (int paramIdx = 0; paramIdx < resPath.getPathParams().size(); paramIdx++) {
Expression pathParam = resPath.getPathParams().get(paramIdx);
if (pathParam.contains(sel.getExpression())) {
for (Map.Entry<Position, Variable> posAndVar : pathParam.getVariables().entrySet()) {
Position p = posAndVar.getKey();
Variable v = posAndVar.getValue();
if (v.equals(sel.getExpression())) {
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> pathToIdxAndPos = channelSelectorToOutputResourcePathParam.get(sel);
if (pathToIdxAndPos == null) {
pathToIdxAndPos = new HashMap<>();
channelSelectorToOutputResourcePathParam.put(sel, pathToIdxAndPos);
}
Map.Entry<Integer, Set<Position>> idxAndPos = pathToIdxAndPos.get(resPath);
if (idxAndPos == null) {
idxAndPos = new AbstractMap.SimpleEntry<>(paramIdx, new HashSet<>());
pathToIdxAndPos.put(resPath, idxAndPos);
}
idxAndPos.getValue().add(p);
}
}
}
}
}
}
}
public DataTransferChannel getChannel() {
return channel;
}
public Expression getMessage() {
return message;
}
public void setMessage(Expression message) {
this.message = message;
}
public boolean isInput() {
return isInput;
}
public List<Map.Entry<Selector, Constant>> getChannelSelectorAndValues() {
return channelSelectorAndValues;
}
public List<Constant> getChannelSelectorValues() {
List<Constant> channelValues = new ArrayList<>();
for (Map.Entry<Selector, Constant> chEnt : channelSelectorAndValues) {
channelValues.add(chEnt.getValue());
}
return channelValues;
}
public void updateChannelSelectorValues(List<Constant> channelSelectorValues) {
for (int i = 0; i < channelSelectorValues.size(); i++) {
Map.Entry<Selector, Constant> chEnt = channelSelectorAndValues.get(i);
chEnt.setValue(channelSelectorValues.get(i));
}
}
public Map<Expression, Expression> getDependingParameters() {
return dependingParameters;
}
public void addChild(Event child) {
childEvents.add(child);
}
public Set<Event> getChildren() {
return childEvents;
}
/**
* Construct channel message, collect descendant events of this event and update the values of the depending channel selectors
*
* @param resourceStateValueProvider a resourceStateValueProvider to provide current and next resource states
* @return calculated message constraint by this event
*/
public Expression constructMessageAndDescendantEvents(IResourceStateValueProvider resourceStateValueProvider, boolean doesUpdateDependingParameters) {
try {
Map<ChannelMember, Set<Position>> substitutedPositionsInMessageFromChannels = new HashMap<>();
return constructMessageAndDesdendantEvents(resourceStateValueProvider, substitutedPositionsInMessageFromChannels, doesUpdateDependingParameters);
} catch (ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed e) {
e.printStackTrace();
}
return null;
}
private Expression constructMessageAndDesdendantEvents(IResourceStateValueProvider resourceStateValueProvider,
Map<ChannelMember, Set<Position>> substitutedPositionsInMessageFromChannels, boolean doesUpdateDependingParameters)
throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork, UnificationFailed {
Expression unifiedMessage = null;
Expression messageConstraint = null;
if (message != null) {
unifiedMessage = (Term) message.clone();
}
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);
}
};
// 1. Calculate message constraints from leaf channel members on the 'channel member dependency graph'.
Map<ChannelMember, Set<ChannelMember>> dependency = channel.getMemberDependency();
if (dependency.size() == 0) {
// No channel member dependency.
for (ChannelMember channelMember : channel.getInputChannelMembers()) {
// Calculate message constraint from an input state transition
messageConstraint = channel.calcMessageConstraintForInputMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels);
if (unifiedMessage == null) {
unifiedMessage = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
}
for (ChannelMember channelMember : channel.getReferenceChannelMembers()) {
// Calculate message constraint from a reference state transition
messageConstraint = channel.calcMessageConstraintForReferenceMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels);
if (unifiedMessage == null) {
unifiedMessage = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
}
} else {
Set<ChannelMember> toResolve = new HashSet<>();
Set<ChannelMember> resolved = new HashSet<>();
for (Set<ChannelMember> depended : dependency.values()) {
toResolve.addAll(depended);
}
for (ChannelMember depending : dependency.keySet()) {
toResolve.remove(depending);
}
if ((messageConstraint = getMessage()) instanceof Term) {
unifiedMessage = messageConstraint;
}
for (ChannelMember leafMember : toResolve) {
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 = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
}
resolved.addAll(toResolve);
toResolve.clear();
// 2. Calculate message constraints from remaining members on the channel member dependency graph.
for (; ; ) {
// Identify the channel members to resolve next.
for (Map.Entry<ChannelMember, Set<ChannelMember>> dependEnt : dependency.entrySet()) {
ChannelMember dependingMem = dependEnt.getKey();
Set<ChannelMember> 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.
if (doesUpdateDependingParameters) {
Set<Position> dependingVarPosInMessage = new HashSet<>();
ResourcePath filledResPath = channel.fillOutsideResourcePath(dependingMem.getResource(), unifiedMessage, dependingMem.getStateTransition().getMessageExpression(), dependingVarPosInMessage);
ResourcePath unfilledResPath = dependingMem.getResource();
for (int i = 0; i < unfilledResPath.getPathParamsAndConstraints().size(); i++) {
Expression var = unfilledResPath.getPathParamsAndConstraints().get(i).getKey();
Expression val = filledResPath.getPathParamsAndConstraints().get(i).getKey();
Expression constraint = unfilledResPath.getPathParamsAndConstraints().get(i).getValue();
if (constraint != null && !constraint.equals(val)) {
// The value of the path parameter does not satisfy the constraint defined for the parameter.
return null; // Not to fire this event.
}
if (!channel.getAllSelectorVariables().contains(var)) {
// Update a depending channel parameter
updateDependingParameter(var, val);
}
}
}
// Calculate message constraint
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 = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
}
resolved.addAll(toResolve);
toResolve.clear();
}
// For the channel members that are depended by and depend on no other member.
for (ChannelMember remainingMem : channel.getChannelMembers()) {
if (!resolved.contains(remainingMem)) {
resolved.add(remainingMem);
// Calculate message constraint
messageConstraint = null;
if (channel.getInputChannelMembers().contains(remainingMem)) {
// Calculate message constraint from an input state transition
messageConstraint = channel.calcMessageConstraintForInputMember(remainingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels);
} else if (channel.getReferenceChannelMembers().contains(remainingMem)) {
// Calculate message constraint from a reference state transition
messageConstraint = channel.calcMessageConstraintForReferenceMember(remainingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels);
}
if (messageConstraint != null) {
if (unifiedMessage == null) {
unifiedMessage = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
}
}
}
}
if (inputResource == null) return unifiedMessage;
// 3. Propagate parent event message to collect child events and calculate message constraints from child channels.
Resource baseResource = inputResource;
while (baseResource.getResourceHierarchy().getNumParameters() == 0) {
if (baseResource.getParent() == null) break;
baseResource = baseResource.getParent();
}
Expression parentEventMessage = (Expression) unifiedMessage.clone();
for (Channel childChannel : channel.getChildren()) {
// Search the deepest input or reference side resource path in each child channel that matches the channel parameters.
ChannelMember inOrRef = null;
Set<ChannelMember> channelMembers = new HashSet<>(((DataTransferChannel) childChannel).getInputChannelMembers());
channelMembers.addAll(((DataTransferChannel) childChannel).getReferenceChannelMembers());
for (ChannelMember cm : channelMembers) {
if (!cm.isOutside()) {
ResourcePath resPath = cm.getResource();
if (resPath.getPathParams().containsAll(childChannel.getAllSelectorVariables())) {
inOrRef = cm;
break;
}
}
}
if (inOrRef != null) {
// Collect events for all resources under this event's input resource that matches the deepest input side resource path.
for (Resource res : baseResource.getDescendants(inOrRef.getResource().getResourceHierarchy())) {
Event childEvent = new Event((DataTransferChannel) childChannel, inOrRef.getResource(), res);
childEvent.setMessage(parentEventMessage);
messageConstraint = childEvent.constructMessageAndDesdendantEvents(resourceStateValueProvider, substitutedPositionsInMessageFromChannels, true);
if (messageConstraint != null) {
childEvent.setMessage(messageConstraint);
if (unifiedMessage == null) {
unifiedMessage = messageConstraint;
} else {
unifiedMessage = unifiedMessage.unify(messageConstraint);
if (unifiedMessage == null) {
throw new UnificationFailed();
}
}
childEvents.add(childEvent);
}
}
} else {
// Search the deepest output side resource path in each child channel that matches the channel parameters.
ChannelMember out = null;
for (ChannelMember cm : ((DataTransferChannel) childChannel).getOutputChannelMembers()) {
if (!cm.isOutside()) {
ResourcePath resPath = cm.getResource();
if (resPath.getPathParams().containsAll(childChannel.getAllSelectorVariables())) {
out = cm;
break;
}
}
}
if (out != null) {
// Collect events for all resources under this event's input resource that matches the deepest output side resource path.
for (Resource res : baseResource.getDescendants(out.getResource().getResourceHierarchy())) {
Event childEvent = new Event((DataTransferChannel) childChannel, parentEventMessage, out.getResource(), res);
childEvent.constructMessageAndDesdendantEvents(resourceStateValueProvider, substitutedPositionsInMessageFromChannels, true);
childEvents.add(childEvent);
}
}
}
}
return unifiedMessage;
}
public void updateDependingParameter(Expression variable, Expression value) {
dependingParameters.put(variable, value);
}
public ResourcePath getInputResourcePath() {
return inputResourcePath;
}
public Resource getInputResource() {
return inputResource;
}
public Set<Resource> getOutputResources() {
return outputResources;
}
public ResourceIdentifier getResourceIdentifier(ResourcePath resPath) {
ResourceIdentifier resId = ResourceIdentifier.createFrom(resPath);
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> inputPathToIdxAndPos = channelSelectorToInputOrReferenceResourcePathParam.get(sel);
if (inputPathToIdxAndPos != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = inputPathToIdxAndPos.get(resPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Variable) {
resId.setPathParam(paramIdx, chParamEnt.getValue());
}
}
}
}
}
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> outputPathToIdxAndPos = channelSelectorToOutputResourcePathParam.get(sel);
if (outputPathToIdxAndPos != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = outputPathToIdxAndPos.get(resPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Variable) {
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));
}
}
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> inputPathToIdxAndPos = channelSelectorToInputOrReferenceResourcePathParam.get(sel);
if (inputPathToIdxAndPos != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = inputPathToIdxAndPos.get(resPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Term && sel.getExpression() instanceof Variable) {
pathParamExp = ((Term) pathParamExp).substitute((Variable) sel.getExpression(), chParamEnt.getValue());
resId.setPathParam(paramIdx, ((Term) pathParamExp).reduce());
}
}
}
}
}
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
Map<ResourcePath, Map.Entry<Integer, Set<Position>>> outputPathToIdxAndPos = channelSelectorToOutputResourcePathParam.get(sel);
if (outputPathToIdxAndPos != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = outputPathToIdxAndPos.get(resPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Term && sel.getExpression() instanceof Variable) {
pathParamExp = ((Term) pathParamExp).substitute((Variable) sel.getExpression(), chParamEnt.getValue());
resId.setPathParam(paramIdx, ((Term) pathParamExp).reduce());
}
}
}
}
}
return resId;
}
public ResourceIdentifier getInputResourceIdentifier(ResourcePath inputResPath) {
ResourceIdentifier resId = ResourceIdentifier.createFrom(inputResPath);
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
if (channelSelectorToInputOrReferenceResourcePathParam.get(sel) != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = channelSelectorToInputOrReferenceResourcePathParam.get(sel).get(inputResPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Variable) {
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));
}
}
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
if (channelSelectorToInputOrReferenceResourcePathParam.get(sel) != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = channelSelectorToInputOrReferenceResourcePathParam.get(sel).get(inputResPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Term && sel.getExpression() instanceof Variable) {
pathParamExp = ((Term) pathParamExp).substitute((Variable) sel.getExpression(), chParamEnt.getValue());
resId.setPathParam(paramIdx, ((Term) pathParamExp).reduce());
}
}
}
}
}
return resId;
}
public ResourceIdentifier getOutputResourceIdentifier(ResourcePath outputResPath) {
ResourceIdentifier resId = ResourceIdentifier.createFrom(outputResPath);
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
if (channelSelectorToOutputResourcePathParam.get(sel) != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Variable) {
resId.setPathParam(paramIdx, chParamEnt.getValue());
}
}
}
}
}
for (Expression var : dependingParameters.keySet()) {
int paramIdx = resId.getPathParams().indexOf(var);
if (paramIdx >= 0) {
resId.setPathParam(paramIdx, dependingParameters.get(var));
}
}
for (Map.Entry<Selector, Constant> chParamEnt : channelSelectorAndValues) {
Selector sel = chParamEnt.getKey();
if (channelSelectorToOutputResourcePathParam.get(sel) != null) {
Map.Entry<Integer, Set<Position>> pathParamEnt = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath);
if (pathParamEnt != null) {
Integer paramIdx = pathParamEnt.getKey();
if (paramIdx != null) {
Expression pathParamExp = resId.getPathParams().get(paramIdx);
if (pathParamExp instanceof Term && sel.getExpression() instanceof Variable) {
pathParamExp = ((Term) pathParamExp).substitute((Variable) sel.getExpression(), chParamEnt.getValue());
resId.setPathParam(paramIdx, ((Term) pathParamExp).reduce());
}
}
}
}
}
return resId;
}
public interface IResourceStateValueProvider {
Expression getCurrentStateValueOf(ResourceIdentifier resId);
Expression getNextStateValueOf(ResourceIdentifier resId);
}
}