diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java index 569fe28..fb04068 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import javax.swing.BorderFactory; import javax.swing.JComboBox; @@ -36,12 +37,15 @@ import models.algebra.Expression; import models.algebra.InvalidMessage; import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Position; import models.algebra.Term; +import models.algebra.Type; 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.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; @@ -103,45 +107,41 @@ stopEditing(true); } if (!graphComponent.getGraph().getModel().isEdge(cell)) { - Resource res = simulator.getCurState().getResource((String) ((mxCell) cell).getValue()); ResourceIdentifier resId = res.getResourceIdentifier(); // clicked resource - ArrayList eventChs = new ArrayList<>(); // eventchannelList - ArrayList messages = new ArrayList<>(); // ADLmessage - ArrayList eventMessages = new ArrayList<>(); // messageList + ArrayList eventChs = new ArrayList<>(); // event channel list + ArrayList messageTexts = new ArrayList<>(); // message text list + ArrayList messageExps = new ArrayList<>(); // message expression list + ArrayList> refParams = new ArrayList<>(); // message parameters for ref ports ResourcePath eventResPath = null; for (Channel ch: simulator.getModel().getInputChannels()) { // all channels - eventResPath = getSelectableMessages(ch, resId, eventChs, messages, eventMessages, eventResPath); + eventResPath = getSelectableMessages(ch, resId, eventChs, messageTexts, messageExps, refParams, eventResPath); } - - if (messages.isEmpty()) { + if (messageTexts.isEmpty()) { return; } - String[] eventList = messages.toArray(new String[messages.size()]); - JComboBox event = new JComboBox(eventList); + String[] messageList = messageTexts.toArray(new String[messageTexts.size()]); + JComboBox messageMenu = new JComboBox(messageList); - JPanel eventChoice = new JPanel(); - eventChoice.add(event); // FirstEventChoice + JPanel eventSelectPanel = new JPanel(); + eventSelectPanel.add(messageMenu); - int ret = JOptionPane.showConfirmDialog(window, eventChoice, "Event Choice", JOptionPane.OK_CANCEL_OPTION); + int ret = JOptionPane.showConfirmDialog(window, eventSelectPanel, "Event Choice", JOptionPane.OK_CANCEL_OPTION); // Select an event. if (ret == JOptionPane.OK_OPTION) { - - JPanel inputEvent = new JPanel(); - int i , eventNum; - i = eventNum = 0; - - for (String eventString : eventList) { - if(eventString.equals(event.getSelectedItem().toString())) { - eventNum = i; + int i, messageIdx; + i = messageIdx = 0; + for (String messageText : messageList) { + if(messageText.equals(messageMenu.getSelectedItem().toString())) { + messageIdx = i; } i++; } - - JTextArea textArea = new JTextArea(eventMessages.get(eventNum).toString(), 10, 30); // EventInput - inputEvent.add(textArea); - - int approve = JOptionPane.showConfirmDialog(window, inputEvent, "Event Code", JOptionPane.OK_CANCEL_OPTION); + JPanel inputEventPanel = new JPanel(); + JTextArea textArea = new JTextArea(messageExps.get(messageIdx).toString(), 10, 30); + inputEventPanel.add(textArea); + + int approve = JOptionPane.showConfirmDialog(window, inputEventPanel, "Event Code", JOptionPane.OK_CANCEL_OPTION); // Input an message text for the event. if (approve == JOptionPane.OK_OPTION) { try { @@ -149,8 +149,15 @@ Parser parser = new Parser(stream); stream.addLine(textArea.getText()); Expression eventMessage = parser.parseTerm(stream, simulator.getModel()); + if (eventMessage instanceof Term) { + TreeMap refMap = refParams.get(messageIdx); + for (Integer paramIdx: refMap.keySet()) { + ((Term) eventMessage).getSymbol().setArity(-1); + ((Term) eventMessage).addChild(paramIdx, refMap.get(paramIdx), true); + } + } - Event newEvent = new Event(eventChs.get(eventNum), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); + Event newEvent = new Event(eventChs.get(messageIdx), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); simulator.transition(newEvent); graphComponent.setCellEditor(new InputEventCellEditor(window, graphComponent, simulator, this.editor)); @@ -186,38 +193,61 @@ } private ResourcePath getSelectableMessages(Channel ch, ResourceIdentifier resId, - ArrayList eventChs, ArrayList messages, ArrayList eventMessages, + ArrayList eventChs, ArrayList messageTexts, ArrayList messageExps, ArrayList> refParams, ResourcePath eventResPath) { - if (((DataTransferChannel) ch).getInputResources().size() == 0) { // event ch or normal ch + if (((DataTransferChannel) ch).getInputResources().size() == 0) { // event ch. or normal ch. for (ChannelMember out: ((DataTransferChannel) ch).getOutputChannelMembers()) { ResourcePath resPath = out.getResource(); - if (!out.isOutside() && resId.isInstanceOf(resPath)) { // account.uid == acounts.123 + if (!out.isOutside() && resId.isInstanceOf(resPath)) { eventResPath = resPath; eventChs.add(((DataTransferChannel) ch)); - String message = null; + String messageText = null; Expression mesExp = out.getStateTransition().getMessageExpression(); + TreeMap refMap = new TreeMap<>(); if (mesExp instanceof Term) { + // Reconstruct an input message template List pathParams = resPath.getPathParams(); List children = ((Term) mesExp).getChildren(); mesExp = new Term(((Term) mesExp).getSymbol()); - for (Expression child: children) { - if (!pathParams.contains(child)) { - ((Term) mesExp).addChild(child); + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + boolean isRefVar = false; + for (ChannelMember refCm: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + if (refCm.getStateTransition().getMessageExpression() instanceof Term) { + Expression varExp = ((Term) refCm.getStateTransition().getMessageExpression()).getChild(i); + if (varExp != null && varExp instanceof Variable) { + if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { + // child has come from a reference resource. + isRefVar = true; + break; + } + } + } + } + if (!isRefVar) { + // child has not come from a reference resource. + if (!pathParams.contains(child)) { + ((Term) mesExp).addChild(child); + } else { + int idx = pathParams.indexOf(child); + ((Term) mesExp).addChild(resId.getPathParams().get(idx)); + } } else { - int idx = pathParams.indexOf(child); - ((Term) mesExp).addChild(resId.getPathParams().get(idx)); + // child has come from a reference resource. + refMap.put(i, child); } } - message = ((Term) mesExp).getSymbol().toString(); + messageText = ((Term) mesExp).getSymbol().toString(); } else if(mesExp instanceof Variable) { - message = ((Variable) mesExp).getName(); + messageText = ((Variable) mesExp).getName(); } - eventMessages.add(mesExp); - messages.add(message); // for the pull-down menu + messageExps.add(mesExp); + messageTexts.add(messageText); // for the pull-down menu + refParams.add(refMap); } } for (Channel childCh: ch.getChildren()) { - eventResPath = getSelectableMessages(childCh, resId, eventChs, messages, eventMessages, eventResPath); + eventResPath = getSelectableMessages(childCh, resId, eventChs, messageTexts, messageExps, refParams, eventResPath); } } return eventResPath; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index a4b6fa6..80eabeb 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -1912,21 +1912,23 @@ if (!referredSet.contains(ref)) { referredSet.add(ref); String[] sideEffects = new String[] {""}; - if (!platformSpec.isMonolithic() && rc.isOutside()) { + ResourcePath srcRes = in.getResource(); + if (!generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + if (!platformSpec.isMonolithic() + && (rc.isOutside() || (ref.getCommonPrefix(srcRes) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { List pathParams = new ArrayList<>(); for (Expression pathExp: ref.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } generatePullDataTransfer(update, refVarName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType, false, platformSpec, langSpec); } else { - ResourcePath srcRes = in.getResource(); - if (!generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, srcRes); String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - update.addStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + update.addStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); } } refParams.add(new AbstractMap.SimpleEntry<>(ref.getResourceStateType(), @@ -2520,36 +2522,6 @@ if (input != null) { // Add a statement to update the state field to the input method. try { - if (!platformSpec.hasMain()) { - // For an application with no main component, the reference resource is accessed from each resource. - for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (!out.getResource().equals(ref)) { - String refResourceName = ref.getLeafResourceName(); - Type refResourceType = ref.getResourceStateType(); - String[] sideEffects = new String[] {""}; - if (!platformSpec.isMonolithic() && rc.isOutside()) { - List pathParams = new ArrayList<>(); - for (Expression pathExp: ref.getPathParams()) { - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType, true, platformSpec, langSpec); - } else { - ResourcePath dstRes = out.getResource(); - if (!generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } - Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, dstRes); - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = refResourceType.getInterfaceTypeName(); - input.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refResourceName) - + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); - } - } - } - } - Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor(platformSpec)).getKey(); // Replace Json constructor with a constructor of a descendant resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -2617,6 +2589,37 @@ } } } + if (!platformSpec.hasMain()) { + // For an application with no main component, the reference resource is accessed from each resource. + for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + ResourcePath ref = rc.getResource(); + if (!out.getResource().equals(ref)) { + String refResourceName = ref.getLeafResourceName(); + Type refResourceType = ref.getResourceStateType(); + String[] sideEffects = new String[] {""}; + ResourcePath dstRes = out.getResource(); + if (!generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + if (!platformSpec.isMonolithic() + && (rc.isOutside() || (ref.getCommonPrefix(dstRes) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType, true, platformSpec, langSpec); + } else { + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, dstRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = refResourceType.getInterfaceTypeName(); + input.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refResourceName) + + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + } + } + } + if (rootInputAccessor != null) { // In the root resource // The expression of the receiver (resource) of the input method. diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 42c2067..fdfd502 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -496,17 +496,17 @@ if (!referredSet.contains(ref)) { referredSet.add(ref); String[] sideEffects = new String[] {""}; - if (rc.isOutside()) { + ResourcePath srcRes = in.getResource(); + if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + if (rc.isOutside() || (ref.getCommonPrefix(srcRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { List pathParams = new ArrayList<>(); for (Expression pathExp: ref.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } generatePullDataTransfer(srcUpdate, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); } else { - ResourcePath srcRes = in.getResource(); - if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -680,17 +680,17 @@ if (!referredSet.contains(ref)) { referredSet.add(ref); String[] sideEffects = new String[] {""}; - if (rc.isOutside()) { + ResourcePath srcRes = in.getResource(); + if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + if (rc.isOutside() || (ref.getCommonPrefix(srcRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { List pathParams = new ArrayList<>(); for (Expression pathExp: ref.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } generatePullDataTransfer(srcInput, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); } else { - ResourcePath srcRes = in.getResource(); - if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -850,7 +850,11 @@ ResourcePath refRes = rc.getResource(); String refResourceName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(refRes.getResourceHierarchy())); Type refResourceType = refRes.getResourceStateType(); - if (rc.isOutside()) { + ResourcePath dstRes = out.getResource(); + if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + if (rc.isOutside() || (refRes.getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { List pathParams = new ArrayList<>(); for (Expression pathExp: refRes.getPathParams()) { sideEffects = new String[] {""}; @@ -858,10 +862,6 @@ } generatePullDataTransfer(getter, refResourceName, refRes.getResourceHierarchy().toResourcePath(pathParams), refResourceType); } else { - ResourcePath dstRes = out.getResource(); - if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(refRes, dstRes); sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); @@ -1217,17 +1217,17 @@ if (!referredSet.contains(ref)) { referredSet.add(ref); String[] sideEffects = new String[] {""}; - if (rc.isOutside()) { + ResourcePath dstRes = out.getResource(); + if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + if (rc.isOutside() || (ref.getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { List pathParams = new ArrayList<>(); for (Expression pathExp: ref.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); } else { - ResourcePath dstRes = out.getResource(); - if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, dstRes); String refExp = refGetter.toImplementation(sideEffects); String refTypeName = refResourceType.getInterfaceTypeName(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index 07993fa..9cc7de2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -65,6 +65,11 @@ children.add(child); } + public void addChild(int n, Expression child, boolean bForced) { + if (!bForced && getArity() != -1 && children.size() >= getArity()) return; + children.add(n, child); + } + public Expression getChild(int n) { return children.get(n); } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 2a93a6e..f178c68 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -101,7 +101,10 @@ public SystemState transition(Event inputEvent) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { SystemState nextSystemState = new SystemState(curState); - inputEvent.constructMessageAndDescendantEvents(new ResourceStateValueProvider(curState, nextSystemState), true); + Expression message = inputEvent.constructMessageAndDescendantEvents(new ResourceStateValueProvider(curState, nextSystemState), true); + if (message != null) { + inputEvent.setMessage(message); + } nextSystemState.addEvent(inputEvent); fireEvent(inputEvent, curState, nextSystemState);