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.dataConstraintModel.ResourceHierarchy; import models.dataFlowModel.DataTransferChannel; import simulator.states.CompositeResourceState; 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<Resource> rootResources = new HashSet<>(); private Map<DataTransferChannel, ChannelState> channelStates = new HashMap<>(); private List<Event> events = new ArrayList<>(); public SystemState() { } public SystemState(SystemState prevState) { for (Resource resource: prevState.getRootResources()) { rootResources.add(new Resource(resource)); } for (Map.Entry<DataTransferChannel, ChannelState> channelEnt: prevState.getChannelStates().entrySet()) { if (channelEnt.getValue() != null) { channelStates.put(channelEnt.getKey(), (ChannelState) channelEnt.getValue().clone()); } else { channelStates.put(channelEnt.getKey(), null); } } } public Set<Resource> getRootResources() { return rootResources; } public void addResource(Resource rootResource) { 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 Resource getResource(String resourceIdentifier) { for (Resource root: rootResources) { Resource descendant = root.getDescendant(resourceIdentifier); if (descendant != null) return descendant; } return null; } /** * update the state of a specified resource * * @param resourceIdentifier a resource identifier to identify the resource * @param resStateValue a new state of the resource * @return */ public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { Type resType = resourceIdentifier.getResourceStateType(); if (resType != null && 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 = null; if (state instanceof ListResourceState) { childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); } else if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { // If the value of state is nil. childExp = new Constant("0"); ResourceState parentState = res.getParent().getState(); ResourceState newState = new ListResourceState(); if (parentState instanceof CompositeResourceState) { ((CompositeResourceState) parentState).replaceChildState(state, newState); } state = newState; res.changeState(state); } ResourceHierarchy childResourceHierarchy = null; if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { childResourceHierarchy = resourceIdentifier.getResourceHierarchy().getChildren().iterator().next(); } else { childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); Map.Entry<ResourceState, ResourceIdentifier> childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); ((ListResourceState) state).addChildState(childInfo.getKey()); return childInfo.getValue(); } } } else if (resType != null && 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(); if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { // If the value of state is nil. ResourceState parentState = res.getParent().getState(); ResourceState newState = new MapResourceState(); if (parentState instanceof CompositeResourceState) { ((CompositeResourceState) parentState).replaceChildState(state, newState); } state = newState; res.changeState(state); } ResourceHierarchy childResourceHierarchy = null; if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { childResourceHierarchy = resourceIdentifier.getResourceHierarchy().getChildren().iterator().next(); } else { childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); String childId = ((Constant) childExp).toString(); Map.Entry<ResourceState, ResourceIdentifier> childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); ((MapResourceState) state).addChildState(childId, childInfo.getKey()); return childInfo.getValue(); } } } } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); ResourceIdentifier createdResource = null; while (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { Expression childExp = jsonValue.getChild(1); if (childExp instanceof Constant) { String memberName = ((Constant) childExp).getSymbol().getName().replace("\"", ""); ResourceHierarchy childResourceHierarchy = null; for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { if (childRes.getResourceName().equals(memberName)) { childResourceHierarchy = childRes; break; } } if (childResourceHierarchy == null) { childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); String childId = ((Constant) childExp).toString(); Map.Entry<ResourceState, ResourceIdentifier> childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); ((JsonResourceState) state).addChildState(childId, childInfo.getKey()); createdResource = childInfo.getValue(); } if (!(jsonValue.getChild(0) instanceof Term)) break; jsonValue = (Term) jsonValue.getChild(0); } return createdResource; } } else { if (resStateValue instanceof Constant) { Resource res = getResource(resourceIdentifier); ResourceState state = null; if (res != null) { state = res.getState(); ((PrimitiveResourceState) state).setValue((Constant) resStateValue); } else { 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.getLeafResourceName() + "\"", new PrimitiveResourceState((Constant) resStateValue)); } } return resourceIdentifier; } } return resourceIdentifier; } public Map.Entry<ResourceState, ResourceIdentifier> createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { Type resType = null; if (resStateValue instanceof Term) { resType = ((Term) resStateValue).getType(); resStateValue = ((Term) resStateValue).reduce(); } 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<ResourceState, ResourceIdentifier> 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<ResourceState, ResourceIdentifier> 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; JsonResourceState state = new JsonResourceState(); Map.Entry<ResourceState, ResourceIdentifier> createInfo = null; while (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { Expression childExp = jsonValue.getChild(1); if (childExp instanceof Constant) { String memberName = ((Constant) childExp).getSymbol().getName().replace("\"", ""); ResourceHierarchy childResourceHierarchy = null; for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { if (childRes.getResourceName().equals(memberName)) { childResourceHierarchy = childRes; break; } } if (childResourceHierarchy == null) { childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); String childId = ((Constant) childExp).toString(); Map.Entry<ResourceState, ResourceIdentifier> childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); state.addChildState(childId, childInfo.getKey()); createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); } if (!(jsonValue.getChild(0) instanceof Term)) break; jsonValue = (Term) jsonValue.getChild(0); } return createInfo; } } } 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<DataTransferChannel, ChannelState> 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<Event> getEvents() { return events; } public void addEvent(Event event) { events.add(event); } }