/*
* Initial version copyright 2008 Lockheed Martin Corporation, except
* as stated in the file entitled Licensing-Information.
*
* All modifications copyright 2009-2013 Data Access Technologies, Inc.
*
* Licensed under the Academic Free License version 3.0
* (http://www.opensource.org/licenses/afl-3.0.php), except as stated
* in the file entitled Licensing-Information.
*/
package fUML.Semantics.Activities.CompleteStructuredActivities;
import fUML.Debug;
import UMLPrimitiveTypes.*;
import fUML.Syntax.*;
import fUML.Syntax.Classes.Kernel.*;
import fUML.Syntax.CommonBehaviors.BasicBehaviors.*;
import fUML.Syntax.CommonBehaviors.Communications.*;
import fUML.Syntax.Activities.IntermediateActivities.*;
import fUML.Syntax.Activities.CompleteStructuredActivities.*;
import fUML.Syntax.Actions.BasicActions.*;
import fUML.Semantics.*;
import fUML.Semantics.Classes.Kernel.*;
import fUML.Semantics.CommonBehaviors.BasicBehaviors.*;
import fUML.Semantics.Activities.IntermediateActivities.*;
import fUML.Semantics.Actions.BasicActions.*;
import fUML.Semantics.Loci.*;
public class LoopNodeActivation
extends
fUML.Semantics.Activities.CompleteStructuredActivities.StructuredActivityNodeActivation {
public fUML.Semantics.Activities.CompleteStructuredActivities.ValuesList bodyOutputLists = new fUML.Semantics.Activities.CompleteStructuredActivities.ValuesList();
public boolean isTerminateAll = false;
public void doStructuredActivity() {
// Set the initial values for the body outputs to the values of the loop
// variable input pins.
// If isTestedFirst is true, then repeatedly run the test part and the
// body part of the loop, copying values from the body outputs to the
// loop variables.
// If isTestedFirst is false, then repeatedly run the body part and the
// test part of the loop, copying values from the body outputs to the
// loop variables.
// When the test fails, copy the values of the body outputs to the loop
// outputs.
// [Note: The body outputs are used for the loop outputs, rather than
// the loop variables, since values on the loop variables may be
// consumed when running the test for the last time.]
LoopNode loopNode = (LoopNode) (this.node);
InputPinList loopVariableInputs = loopNode.loopVariableInput;
this.bodyOutputLists.clear();
for (int i = 0; i < loopVariableInputs.size(); i++) {
InputPin loopVariableInput = loopVariableInputs.getValue(i);
Values bodyOutputList = new Values();
bodyOutputList.values = this.takeTokens(loopVariableInput);
this.bodyOutputLists.addValue(bodyOutputList);
}
this.isTerminateAll = false;
this.doLoop(true);
} // doStructuredActivity
public void doLoop(boolean continuing) {
// If isTestedFirst is true, then repeatedly run the test part and the
// body part of the loop, copying values from the body outputs to the
// loop variables.
// If isTestedFirst is false, then repeatedly run the body part and the
// test part of the loop, copying values from the body outputs to the
// loop variables.
LoopNode loopNode = (LoopNode) (this.node);
OutputPinList loopVariables = loopNode.loopVariable;
OutputPinList resultPins = loopNode.result;
while (continuing) {
// Set loop variable values
this.runLoopVariables();
for (int i = 0; i < loopVariables.size(); i++) {
OutputPin loopVariable = loopVariables.getValue(i);
Values bodyOutputList = bodyOutputLists.getValue(i);
ValueList values = bodyOutputList.values;
this.putPinValues(loopVariable, values);
((OutputPinActivation) this.activationGroup
.getNodeActivation(loopVariable)).sendUnofferedTokens();
}
// Run all the non-executable, non-pin nodes in the conditional
// node.
ActivityNodeActivationList nodeActivations = this.activationGroup.nodeActivations;
ActivityNodeActivationList nonExecutableNodeActivations = new ActivityNodeActivationList();
for (int i = 0; i < nodeActivations.size(); i++) {
ActivityNodeActivation nodeActivation = nodeActivations
.getValue(i);
if (!(nodeActivation.node instanceof ExecutableNode | nodeActivation.node instanceof Pin)) {
nonExecutableNodeActivations.addValue(nodeActivation);
}
}
this.activationGroup.run(nonExecutableNodeActivations);
// Run the loop
if (loopNode.isTestedFirst) {
continuing = this.runTest();
if (continuing) {
this.runBody();
}
} else {
this.runBody();
if (this.isRunning() & !this.isSuspended()) {
continuing = this.runTest();
}
}
if (!this.isTerminateAll & this.isRunning() & !this.isSuspended()) {
this.activationGroup.terminateAll();
} else {
continuing = false;
}
Debug.println("[doStructuredActivity] "
+ (continuing ? "Continuing.": this.isSuspended() ? "Suspended" : "Done."));
}
if (!this.isTerminateAll & this.isRunning() & !this.isSuspended()) {
for (int i = 0; i < bodyOutputLists.size(); i++) {
Values bodyOutputList = bodyOutputLists.getValue(i);
OutputPin resultPin = resultPins.getValue(i);
this.putTokens(resultPin, bodyOutputList.values);
}
}
} // doLoop
public boolean runTest() {
// Run the test part of the loop node for this node activation.
// Return the value on the decider pin.
Debug.println("[runTest] Running test...");
LoopNode loopNode = (LoopNode) (this.node);
this.activationGroup.runNodes(this.makeActivityNodeList(loopNode.test));
ValueList values = this.getPinValues(loopNode.decider);
// If there is no decider value, treat it as false.
boolean decision = false;
if (values.size() > 0) {
decision = ((BooleanValue) (values.getValue(0))).value;
}
Debug.println("[runTest] " + (decision ? "Test succeeded." : "Test failed."));
return decision;
} // runTest
public void runBody() {
// Run the body part of the loop node for this node activation and save
// the body outputs.
Debug.println("[runBody] Running body...");
LoopNode loopNode = (LoopNode) this.node;
this.activationGroup.runNodes(this
.makeActivityNodeList(loopNode.bodyPart));
if (!this.isTerminateAll & !this.isSuspended()) {
this.saveBodyOutputs();
}
} // runBody
public void saveBodyOutputs() {
// Save the body outputs for use in the next iteration.
LoopNode loopNode = (LoopNode) this.node;
OutputPinList bodyOutputs = loopNode.bodyOutput;
ValuesList bodyOutputLists = this.bodyOutputLists;
for (int i = 0; i < bodyOutputs.size(); i++) {
OutputPin bodyOutput = bodyOutputs.getValue(i);
Values bodyOutputList = bodyOutputLists.getValue(i);
bodyOutputList.values = this.getPinValues(bodyOutput);
}
} // saveBodyOutputs
public void runLoopVariables() {
// Run the loop variable pins of the loop node for this node activation.
this.activationGroup.runNodes(this.makeLoopVariableList());
} // runLoopVariables
public void createNodeActivations() {
// In addition to creating activations for contained nodes, create
// activations for any loop variables.
super.createNodeActivations();
this.activationGroup.createNodeActivations(this.makeLoopVariableList());
} // createNodeActivations
public fUML.Syntax.Activities.IntermediateActivities.ActivityNodeList makeLoopVariableList() {
// Return an activity node list containing the loop variable pins for
// the loop node of this activation.
LoopNode loopNode = (LoopNode) (this.node);
ActivityNodeList nodes = new ActivityNodeList();
OutputPinList loopVariables = loopNode.loopVariable;
for (int i = 0; i < loopVariables.size(); i++) {
OutputPin loopVariable = loopVariables.getValue(i);
nodes.addValue(loopVariable);
}
return nodes;
} // makeLoopVariableList
public void terminateAll() {
// Copy the values of the body outputs to the loop outputs, and then
// terminate all activations in the loop.
this.isTerminateAll = true;
LoopNode loopNode = (LoopNode) this.node;
OutputPinList bodyOutputs = loopNode.bodyOutput;
OutputPinList resultPins = loopNode.result;
for (int i = 0; i < bodyOutputs.size(); i++) {
OutputPin bodyOutput = bodyOutputs.getValue(i);
OutputPin resultPin = resultPins.getValue(i);
this.putTokens(resultPin, this.getPinValues(bodyOutput));
}
super.terminateAll();
} // terminateAll
public void resume() {
// When this loop node is resumed after being suspended, continue with
// its next iteration (if any). Once the loop has completed execution
// without being suspended again, complete the action.
LoopNode loopNode = (LoopNode) (this.node);
this.saveBodyOutputs();
if (!this.isTerminateAll) {
if (loopNode.mustIsolate) {
_beginIsolation();
this.continueLoop();
_endIsolation();
} else {
this.continueLoop();
}
}
if (this.isSuspended()) {
// NOTE: If the subsequent iteration of the loop suspends it again,
// then it is necessary to remove the previous suspension from the
// containing activity node activation group.
this.group.resume(this);
} else {
super.resume();
}
} // resume
public void continueLoop() {
// Continue the loop node when it is resumed after being suspended. If
// isTestedFirst is true, then continue executing the loop. If
// isTestedFirst is false, then run the test to determine whether
// the loop should be continued or completed.
// [Note that this presumes that an accept event action is not allowed
// in the test part of a loop node.]
LoopNode loopNode = (LoopNode) (this.node);
boolean continuing = true;
if (!loopNode.isTestedFirst) {
continuing = this.runTest();
}
if (this.isRunning()) {
this.activationGroup.terminateAll();
this.doLoop(continuing);
}
} // continueLoop
} // LoopNodeActivation