diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 7528793..7e222cb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -51,12 +51,12 @@ // root resource Resource resource = new Resource(res); curState.addResource(resource); - Expression initilValue = res.getInitialValue(); - if (initilValue != null) { - if (initilValue instanceof Term) { - initilValue = ((Term) initilValue).reduce(); + Expression initialValue = res.getInitialValue(); + if (initialValue != null) { + if (initialValue instanceof Term) { + initialValue = ((Term) initialValue).reduce(); } - curState.updateResourceState(resource.getResourceIdentifier(), initilValue); + curState.updateResourceState(resource.getResourceIdentifier(), null, null, initialValue); } } } @@ -145,9 +145,12 @@ */ private void fireEvent(final Event event, final SystemState curSystemState, final SystemState nextSystemState) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + final ChannelMember[] outTarget = new ChannelMember[1]; + final Variable[] outResVar = new Variable[1]; IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { @Override public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + if (target == outTarget[0]) return outResVar[0]; // the current state of each output resource is not to be replaced with its value. ResourceIdentifier resId = event.getResourceIdentifier(target.getResource()); Resource res = curSystemState.getResource(resId); if (res == null) return null; @@ -176,7 +179,9 @@ // For each output resource, calculate the next state. for (ChannelMember out: channel.getOutputChannelMembers()) { // Calculate the next state expression. - Expression nextResState = null; + Expression nextResState = null; + outTarget[0] = out; + outResVar[0] = new Variable(channel.getChannelName() + "$" + out.getResource().toString() + "$this"); // A special variable to represent the current state of each output resource. if (!event.isInput()) { nextResState = channel.deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); } else { @@ -189,18 +194,25 @@ nextResState = ((Term) nextResState).substitute((Variable) selExp, selestorAndVal.getValue()); } } - if (nextResState instanceof Term) { - nextResState = ((Term) nextResState).reduce(); - } // Update the resource state. ResourceIdentifier outResId = event.getOutputResourceIdentifier(out.getResource()); - ResourceIdentifier updatedOutResId = nextSystemState.updateResourceState(outResId, nextResState); - 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); + Expression curResState = null; + if (curSystemState.getResource(outResId) != null) { + curResState = curSystemState.getResource(outResId).getState().getValue(); + } + List updatedOutResIds = nextSystemState.updateResourceState(outResId, outResVar[0], curResState, nextResState); + if (updatedOutResIds != null) { + Set ancestors = new HashSet<>(); + for (ResourceIdentifier updatedOutResId: updatedOutResIds) { + while (updatedOutResId != null && !ancestors.contains(updatedOutResId)) { // In addition to the target state, its ancestors' states are also changed. + ancestors.add(updatedOutResId); + for (Event nextEvent: getNextEvents(updatedOutResId, curSystemState, nextSystemState)) { + fireEvent(nextEvent, curSystemState, nextSystemState); + } + if (channel.isNative()) break; // To avoid multiple updates of the same resource. + updatedOutResId = (ResourceIdentifier) updatedOutResId.getParent(); + } } - if (channel.isNative()) break; // To avoid multiple updates of the same resource. - updatedOutResId = (ResourceIdentifier) updatedOutResId.getParent(); } } } else if (channel.isNative()) { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index c101792..a1a0806 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -75,19 +75,41 @@ * 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 + * @param curResVar a variable to represent the current state of the resource (may be replaced with resCurStateVal) + * @param resCurStateVal the value of the current state of the resource + * @param resNextStateVal the value of the new state of the resource (may contain curResVar) + * @return the identifier of the deepest resource created by this update. */ - public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + public List updateResourceState(ResourceIdentifier resourceIdentifier, Variable curResVar, Expression resCurStateVal, Expression resNextStateVal) { Type resType = resourceIdentifier.getResourceStateType(); + if (resNextStateVal instanceof Term) { + Term termValue = (Term) resNextStateVal; + if (termValue.getSymbol().equals(DataConstraintModel.cond)) { + // If resNextStateVal is a conditional term, then calculates it here. + Expression condExp = termValue.getChild(0); + if (condExp instanceof Term) { + condExp = ((Term) condExp).substitute(curResVar, resCurStateVal); + condExp = ((Term) condExp).reduce(); + } + List condArgs = new ArrayList<>(); + condArgs.add(condExp); + condArgs.add(termValue.getChild(1)); + condArgs.add(termValue.getChild(2)); + resNextStateVal = DataConstraintModel.cond.calculate(condArgs); + if (resNextStateVal != null) { + return updateResourceState(resourceIdentifier, curResVar, resCurStateVal, resNextStateVal); + } + return null; + } + } if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { - if (resStateValue instanceof Constant) { - } else if (resStateValue instanceof ListTerm) { - ListTerm listValue = (ListTerm) resStateValue; + if (resNextStateVal instanceof Constant) { + } else if (resNextStateVal instanceof ListTerm) { + ListTerm listValue = (ListTerm) resNextStateVal; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); if (state instanceof ListResourceState) { - ResourceIdentifier createdResource = null; + List createdResources = new ArrayList<>(); ((ListResourceState) state).clearChildStates(); for (int i = 0; i < listValue.size(); i++) { Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); @@ -104,19 +126,42 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, listValue.get(i)); ((ListResourceState) state).addChildState(childInfo.getKey()); - createdResource = childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); } - return createdResource; - } else { - return resourceIdentifier; + return createdResources; } - } else if (resStateValue instanceof Term) { - Term listValue = (Term) resStateValue; + return null; + } else if (resNextStateVal instanceof Term) { + Term listValue = (Term) resNextStateVal; if (listValue.getSymbol().equals(DataConstraintModel.append)) { + List createdResources = new ArrayList<>(); Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); + if (listValue.getChild(0) instanceof Term) { + if (listValue.getChild(0) instanceof Constant && ((Constant) listValue.getChild(0)).getSymbol().equals(DataConstraintModel.nil)) { + // If the child list is nil. + ResourceState parentState = res.getParent().getState(); + ResourceState newState = new ListResourceState(); + if (parentState instanceof CompositeResourceState) { + ((CompositeResourceState) parentState).replaceChildState(state, newState); + } + state = newState; + res.changeState(state); + } else { + Expression childList = ((Term) listValue.getChild(0)).reduce(); + if (childList instanceof ListTerm) { + // If the child list is a list literal. + List childInfo = updateResourceState(resourceIdentifier, curResVar, resCurStateVal, childList); // one more recursion. + if (childInfo != null) createdResources.addAll(childInfo); + } else if (childList instanceof Term) { + // There may or may not be the current state of the resource (curResVar) under the child. + List childInfo = updateResourceState(resourceIdentifier, curResVar, resCurStateVal, listValue.getChild(0)); + createdResources.addAll(childInfo); + } + } + } Expression childExp = null; if (state instanceof ListResourceState) { childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); @@ -144,19 +189,20 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, listValue.getChild(1)); ((ListResourceState) state).addChildState(childInfo.getKey()); - return childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); + return createdResources; } } } else if (resType != null && DataConstraintModel.typeMap.isAncestorOf(resType)) { - if (resStateValue instanceof Constant) { - } else if (resStateValue instanceof JsonTerm) { - JsonTerm mapValue = (JsonTerm) resStateValue; + if (resNextStateVal instanceof Constant) { + } else if (resNextStateVal instanceof JsonTerm) { + JsonTerm mapValue = (JsonTerm) resNextStateVal; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); if (state instanceof MapResourceState) { - ResourceIdentifier createdResource = null; + List createdResources = new ArrayList<>(); ((MapResourceState) state).clearChildStates(); for (String key: mapValue.keySet()) { Expression childExp = new Constant(key, DataConstraintModel.typeString); @@ -173,19 +219,18 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.get(key)); ((MapResourceState) state).addChildState(key, childInfo.getKey()); - createdResource = childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); } - return createdResource; - } else { - return resourceIdentifier; + return createdResources; } - } else if (resStateValue instanceof MapTerm) { - MapTerm mapValue = (MapTerm) resStateValue; + return null; + } else if (resNextStateVal instanceof MapTerm) { + MapTerm mapValue = (MapTerm) resNextStateVal; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); - ResourceIdentifier createdResource = null; + List createdResources = new ArrayList<>(); for (String key: mapValue.keySet()) { Expression childExp = new Constant(key, DataConstraintModel.typeString); ResourceHierarchy childResourceHierarchy = null; @@ -201,18 +246,46 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.get(key)); ((MapResourceState) state).addChildState(key, childInfo.getKey()); - createdResource = childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); } - return createdResource; - } else if (resStateValue instanceof Term) { - Term mapValue = (Term) resStateValue; + return createdResources; + } else if (resNextStateVal instanceof Term) { + Term mapValue = (Term) resNextStateVal; if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { - Expression childExp = mapValue.getChild(1); - if (childExp instanceof Constant) { + List createdResources = new ArrayList<>(); + Expression childKeyExp = mapValue.getChild(1); + if (childKeyExp instanceof Term) { + childKeyExp = ((Term) childKeyExp).substitute(curResVar, resCurStateVal); + childKeyExp = ((Term) childKeyExp).reduce(); + } + if (childKeyExp instanceof Constant) { Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); + if (mapValue.getChild(0) instanceof Term) { + if (mapValue.getChild(0) instanceof Constant && ((Constant) mapValue.getChild(0)).getSymbol().equals(DataConstraintModel.nil)) { + // If the child map 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); + } else { + Expression childMap = ((Term) mapValue.getChild(0)).reduce(); + if (childMap instanceof MapTerm) { + // If the child map is a map literal. + List childInfo = updateResourceState(resourceIdentifier, curResVar, resCurStateVal, childMap); // one more recursion + createdResources.addAll(childInfo); + } else if (childMap instanceof Term) { + // There may or may not be the current state of the resource (curResVar) under the child. + List childInfo = updateResourceState(resourceIdentifier, curResVar, resCurStateVal, mapValue.getChild(0)); + createdResources.addAll(childInfo); + } + } + } if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { // If the value of state is nil. ResourceState parentState = res.getParent().getState(); @@ -235,22 +308,23 @@ } childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } - ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - String childId = ((Constant) childExp).toString(); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childKeyExp, childResourceHierarchy); + String childId = ((Constant) childKeyExp).toString(); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.getChild(2)); ((MapResourceState) state).addChildState(childId, childInfo.getKey()); - return childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); + return createdResources; } } } } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { - if (resStateValue instanceof Constant) { - } else if (resStateValue instanceof JsonTerm) { - JsonTerm jsonValue = (JsonTerm) resStateValue; + if (resNextStateVal instanceof Constant) { + } else if (resNextStateVal instanceof JsonTerm) { + JsonTerm jsonValue = (JsonTerm) resNextStateVal; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); if (state instanceof JsonResourceState) { - ResourceIdentifier createdResource = null; + List createdResources = new ArrayList<>(); for (String key: jsonValue.keySet()) { String memberName = key.replace("\"", ""); ResourceHierarchy childResourceHierarchy = null; @@ -270,27 +344,26 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, jsonValue.get(key)); ResourceState childState = childInfo.getKey(); if (res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { res.getChildrenMap().get(memberName).changeState(childState); } ((JsonResourceState) state).addChildState(memberName, childState); - createdResource = childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); } - return createdResource; - } else { - return resourceIdentifier; + return createdResources; } - } else if (resStateValue instanceof Term) { - Term jsonValue = (Term) resStateValue; + return null; + } else if (resNextStateVal instanceof Term) { + Term jsonValue = (Term) resNextStateVal; Resource res = getResource(resourceIdentifier); ResourceState state = res.getState(); - ResourceIdentifier createdResource = null; + List createdResources = new ArrayList<>(); while (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { - Expression childExp = jsonValue.getChild(1); - if (childExp instanceof Constant) { - String memberName = ((Constant) childExp).getSymbol().getName().replace("\"", ""); + Expression childKeyExp = jsonValue.getChild(1); + if (childKeyExp instanceof Constant) { + String memberName = ((Constant) childKeyExp).getSymbol().getName().replace("\"", ""); ResourceHierarchy childResourceHierarchy = null; for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { if (childRes.getResourceName().equals(memberName)) { @@ -308,42 +381,50 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); - String childId = ((Constant) childExp).toString(); - Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + String childId = ((Constant) childKeyExp).toString(); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, jsonValue.getChild(2)); ((JsonResourceState) state).addChildState(childId, childInfo.getKey()); - createdResource = childInfo.getValue(); + createdResources.addAll(childInfo.getValue()); } if (!(jsonValue.getChild(0) instanceof Term)) break; jsonValue = (Term) jsonValue.getChild(0); } - return createdResource; + return createdResources; } } else { - if (resStateValue instanceof Constant) { + if (curResVar != null && resCurStateVal != null) { + if (resNextStateVal instanceof Term) { + resNextStateVal = ((Term) resNextStateVal).substitute(curResVar, resCurStateVal); + resNextStateVal = ((Term) resNextStateVal).reduce(); + } + } + if (resNextStateVal instanceof Constant) { Resource res = getResource(resourceIdentifier); ResourceState state = null; if (res != null) { state = res.getState(); - ((PrimitiveResourceState) state).setValue((Constant) resStateValue); + ((PrimitiveResourceState) state).setValue((Constant) resNextStateVal); } 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)); + parentState.addChildState(((Constant) resourceIdentifier.getLastParam()).toString(), new PrimitiveResourceState((Constant) resNextStateVal)); } else if (parentResType != null && DataConstraintModel.typeJson.isAncestorOf(parentResType)) { JsonResourceState parentState = (JsonResourceState) getResource(parentResId).getState(); - parentState.addChildState("\"" + resourceIdentifier.getLeafResourceName() + "\"", new PrimitiveResourceState((Constant) resStateValue)); + parentState.addChildState("\"" + resourceIdentifier.getLeafResourceName() + "\"", new PrimitiveResourceState((Constant) resNextStateVal)); } } - return resourceIdentifier; + List updatedResources = new ArrayList<>(); + updatedResources.add(resourceIdentifier); + return updatedResources; } } - return resourceIdentifier; + return null; } - public Map.Entry createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + public Map.Entry> createResourceState(ResourceIdentifier resourceIdentifier, Variable curResVar, Expression resCurStateVal, Expression resStateValue) { Type resType = resourceIdentifier.getResourceStateType(); if (resType == null && resStateValue instanceof Term) { resType = ((Term) resStateValue).getType(); @@ -355,7 +436,7 @@ } else if (resStateValue instanceof ListTerm) { ListTerm listValue = (ListTerm) resStateValue; ListResourceState state = new ListResourceState(); - Map.Entry createInfo = null; + Map.Entry> createInfo = new AbstractMap.SimpleEntry<>(null, new ArrayList<>()); for (int i = 0; i < listValue.size(); i++) { Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); ResourceHierarchy childResourceHierarchy = null; @@ -371,15 +452,37 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, listValue.get(i)); state.addChildState(childInfo.getKey()); - createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createInfo.getValue().addAll(childInfo.getValue()); + createInfo = new AbstractMap.SimpleEntry<>(state, createInfo.getValue()); } return createInfo; } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; if (listValue.getSymbol().equals(DataConstraintModel.append)) { + List createdResources = new ArrayList<>(); ListResourceState state = new ListResourceState(); + if (listValue.getChild(0) instanceof Term) { + if (listValue.getChild(0) instanceof Constant && ((Constant) listValue.getChild(0)).getSymbol().equals(DataConstraintModel.nil)) { + // If the child list is nil. + } else { + Expression childList = ((Term) listValue.getChild(0)); + childList = ((Term) childList).substitute(curResVar, resStateValue); + childList = ((Term) childList).reduce(); + if (childList instanceof ListTerm) { + // If the child list is a list literal. + Map.Entry> childInfo = createResourceState(resourceIdentifier, curResVar, resCurStateVal, childList); // one more recursion. + state = (ListResourceState) childInfo.getKey(); + if (childInfo != null) createdResources.addAll(childInfo.getValue()); + } else if (childList instanceof Term) { + // If the child list is a list term. + Map.Entry> childInfo = createResourceState(resourceIdentifier, curResVar, resCurStateVal, listValue.getChild(0)); + state = (ListResourceState) childInfo.getKey(); + createdResources.addAll(childInfo.getValue()); + } + } + } Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); ResourceHierarchy childResourceHierarchy = null; if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { @@ -394,9 +497,10 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, listValue.getChild(1)); state.addChildState(childInfo.getKey()); - return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createdResources.addAll(childInfo.getValue()); + return new AbstractMap.SimpleEntry<>(state, createdResources); } } } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { @@ -404,7 +508,7 @@ } else if (resStateValue instanceof JsonTerm) { JsonTerm mapValue = (JsonTerm) resStateValue; MapResourceState state = new MapResourceState(); - Map.Entry createInfo = null; + Map.Entry> createInfo = new AbstractMap.SimpleEntry<>(null, new ArrayList<>()); for (String key: mapValue.keySet()) { Expression childExp = new Constant(key, DataConstraintModel.typeString); ResourceHierarchy childResourceHierarchy = null; @@ -420,15 +524,16 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.get(key)); state.addChildState(key, childInfo.getKey()); - createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createInfo.getValue().addAll(childInfo.getValue()); + createInfo = new AbstractMap.SimpleEntry<>(state, createInfo.getValue()); } return createInfo; } else if (resStateValue instanceof MapTerm) { MapTerm mapValue = (MapTerm) resStateValue; MapResourceState state = new MapResourceState(); - Map.Entry createInfo = null; + Map.Entry> createInfo = new AbstractMap.SimpleEntry<>(null, new ArrayList<>()); for (String key: mapValue.keySet()) { Expression childExp = new Constant(key, DataConstraintModel.typeString); ResourceHierarchy childResourceHierarchy = null; @@ -444,9 +549,10 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.get(key)); state.addChildState(key, childInfo.getKey()); - createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createInfo.getValue().addAll(childInfo.getValue()); + createInfo = new AbstractMap.SimpleEntry<>(state, createInfo.getValue()); } return createInfo; } else if (resStateValue instanceof Term) { @@ -454,7 +560,28 @@ if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { Expression childExp = mapValue.getChild(1); if (childExp instanceof Constant) { + List createdResources = new ArrayList<>(); MapResourceState state = new MapResourceState(); + if (mapValue.getChild(0) instanceof Term) { + if (mapValue.getChild(0) instanceof Constant && ((Constant) mapValue.getChild(0)).getSymbol().equals(DataConstraintModel.nil)) { + // If the child list is nil. + } else { + Expression childMap = ((Term) mapValue.getChild(0)); + childMap = ((Term) childMap).substitute(curResVar, resStateValue); + childMap = ((Term) childMap).reduce(); + if (childMap instanceof MapTerm) { + // If the child map is a map literal. + Map.Entry> childInfo = createResourceState(resourceIdentifier, curResVar, resCurStateVal, childMap); // one more recursion. + state = (MapResourceState) childInfo.getKey(); + if (childInfo != null) createdResources.addAll(childInfo.getValue()); + } else if (childMap instanceof Term) { + // If the child map is a map term. + Map.Entry> childInfo = createResourceState(resourceIdentifier, curResVar, resCurStateVal, mapValue.getChild(0)); + state = (MapResourceState) childInfo.getKey(); + createdResources.addAll(childInfo.getValue()); + } + } + } ResourceHierarchy childResourceHierarchy = null; if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { childResourceHierarchy = resourceIdentifier.getResourceHierarchy().getChildren().iterator().next(); @@ -469,9 +596,10 @@ } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); String childId = ((Constant) childExp).toString(); - Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, mapValue.getChild(2)); state.addChildState(childId, childInfo.getKey()); - return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createdResources.addAll(childInfo.getValue()); + return new AbstractMap.SimpleEntry<>(state, createdResources); } } } @@ -480,7 +608,7 @@ } else if (resStateValue instanceof JsonTerm) { JsonTerm jsonValue = (JsonTerm) resStateValue; JsonResourceState state = new JsonResourceState(); - Map.Entry createInfo = null; + Map.Entry> createInfo = new AbstractMap.SimpleEntry<>(null, new ArrayList<>()); for (String key: jsonValue.keySet()) { String memberName = key.replace("\"", ""); ResourceHierarchy childResourceHierarchy = null; @@ -500,20 +628,21 @@ childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName, childResType); } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); - Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, jsonValue.get(key)); ResourceState childState = childInfo.getKey(); Resource res = getResource(resourceIdentifier); if (res != null && res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { res.getChildrenMap().get(memberName).changeState(childState); } state.addChildState(memberName, childState); - createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createInfo.getValue().addAll(childInfo.getValue()); + createInfo = new AbstractMap.SimpleEntry<>(state, createInfo.getValue()); } return createInfo; } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; JsonResourceState state = new JsonResourceState(); - Map.Entry createInfo = null; + Map.Entry> createInfo = new AbstractMap.SimpleEntry<>(null, new ArrayList<>()); while (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { Expression childExp = jsonValue.getChild(1); if (childExp instanceof Constant) { @@ -536,9 +665,10 @@ } ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); String childId = ((Constant) childExp).toString(); - Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + Map.Entry> childInfo = createResourceState(childResourceIdentifier, curResVar, resCurStateVal, jsonValue.getChild(2)); state.addChildState(childId, childInfo.getKey()); - createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + createInfo.getValue().addAll(childInfo.getValue()); + createInfo = new AbstractMap.SimpleEntry<>(state, createInfo.getValue()); } if (!(jsonValue.getChild(0) instanceof Term)) break; jsonValue = (Term) jsonValue.getChild(0); @@ -556,7 +686,9 @@ } else { state = new PrimitiveResourceState((Constant) resStateValue); } - return new AbstractMap.SimpleEntry<>(state, resourceIdentifier); + List updatedResources = new ArrayList<>(); + updatedResources.add(resourceIdentifier); + return new AbstractMap.SimpleEntry<>(state, updatedResources); } return null; }