/* * Initial version copyright 2008 Lockheed Martin Corporation, except * as stated in the file entitled Licensing-Information. * * All modifications copyright 2009-2012 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.ExtraStructuredActivities; import fUML.Debug; import UMLPrimitiveTypes.*; import java.util.Iterator; 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.Activities.ExtraStructuredActivities.*; import fUML.Syntax.Actions.BasicActions.*; import fUML.Semantics.*; import fUML.Semantics.Classes.Kernel.*; import fUML.Semantics.CommonBehaviors.BasicBehaviors.*; import fUML.Semantics.CommonBehaviors.Communications.*; import fUML.Semantics.Activities.IntermediateActivities.*; import fUML.Semantics.Activities.CompleteStructuredActivities.*; import fUML.Semantics.Actions.BasicActions.*; import fUML.Semantics.Loci.*; public class ExpansionRegionActivation extends fUML.Semantics.Actions.BasicActions.ActionActivation { public fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionActivationGroupList activationGroups = new fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionActivationGroupList(); public fUML.Semantics.Activities.ExtraStructuredActivities.TokenSetList inputTokens = new fUML.Semantics.Activities.ExtraStructuredActivities.TokenSetList(); public fUML.Semantics.Activities.ExtraStructuredActivities.TokenSetList inputExpansionTokens = new fUML.Semantics.Activities.ExtraStructuredActivities.TokenSetList(); public int next = 0; public fUML.Semantics.Activities.IntermediateActivities.TokenList takeOfferedTokens() { // Take the tokens from the input pin and input expansion node // activations and save them. super.takeOfferedTokens(); ExpansionRegion region = (ExpansionRegion) (this.node); InputPinList inputPins = region.input; ExpansionNodeList inputElements = region.inputElement; this.inputTokens.clear(); this.inputExpansionTokens.clear(); for (int i = 0; i < inputPins.size(); i++) { InputPin inputPin = inputPins.getValue(i); TokenSet tokenSet = new TokenSet(); tokenSet.tokens = this.getPinActivation(inputPin).takeTokens(); this.inputTokens.addValue(tokenSet); } int n = this.numberOfValues(); for (int i = 0; i < inputElements.size(); i++) { ExpansionNode inputElement = inputElements.getValue(i); ExpansionNodeActivation expansionNodeActivation = this .getExpansionNodeActivation(inputElement); expansionNodeActivation.fire(expansionNodeActivation .takeOfferedTokens()); TokenList tokens = expansionNodeActivation.takeTokens(); TokenSet tokenSet = new TokenSet(); int j = 1; while (j <= n) { tokenSet.tokens.add(tokens.getValue(j - 1)); j = j + 1; } this.inputExpansionTokens.addValue(tokenSet); } return new TokenList(); } // takeOfferedTokens public void doAction() { // If the expansion region has mustIsolate=true, then carry out its // behavior with isolation. // Otherwise just activate it normally. if (((StructuredActivityNode) (this.node)).mustIsolate) { _beginIsolation(); this.doStructuredActivity(); _endIsolation(); } else { this.doStructuredActivity(); } } // doAction public void doStructuredActivity() { // Create a number of expansion region activation groups equal to the // number of values expanded in the region, // setting the region inputs and group inputs for each group. // Run the body of the region in each group, either iteratively or in // parallel. // Add the outputs of each activation group to the corresonding output // expansion node activations. ExpansionRegion region = (ExpansionRegion) this.node; InputPinList inputPins = region.input; ExpansionNodeList inputElements = region.inputElement; ExpansionNodeList outputElements = region.outputElement; this.activationGroups.clear(); int n = this.inputExpansionTokens.getValue(0).tokens.size(); int k = 1; while (k <= n) { ExpansionActivationGroup activationGroup = new ExpansionActivationGroup(); activationGroup.regionActivation = this; activationGroup.index = k; int j = 1; while (j <= inputPins.size()) { OutputPinActivation regionInput = new OutputPinActivation(); regionInput.run(); activationGroup.regionInputs.addValue(regionInput); j = j + 1; } j = 1; while (j <= inputElements.size()) { OutputPinActivation groupInput = new OutputPinActivation(); groupInput.run(); activationGroup.groupInputs.addValue(groupInput); j = j + 1; } j = 1; while (j <= outputElements.size()) { OutputPinActivation groupOutput = new OutputPinActivation(); groupOutput.run(); activationGroup.groupOutputs.addValue(groupOutput); j = j + 1; } activationGroup.createNodeActivations(region.node); activationGroup.createEdgeInstances(region.edge); this.activationGroups.addValue(activationGroup); k = k + 1; } // ExpansionActivationGroupList activationGroups = this.activationGroups; if (region.mode == ExpansionKind.iterative) { Debug.println("[doStructuredActivity] Expansion mode = iterative"); this.next = 1; this.runIterative(); } else if (region.mode == ExpansionKind.parallel) { Debug.println("[doStructuredActivity] Expansion mode = parallel"); this.runParallel(); } this.doOutput(); } // doStructuredActivity public void runIterative() { // Run the body of the region iteratively, either until all activation // groups have run or until the region is suspended. ExpansionActivationGroupList activationGroups = this.activationGroups; while (this.next <= activationGroups.size() & !this.isSuspended()) { ExpansionActivationGroup activationGroup = activationGroups .getValue(this.next - 1); this.runGroup(activationGroup); this.next = this.next + 1; } } // runIterative public void runParallel() { // Run the body of the region concurrently. ExpansionActivationGroupList activationGroups = this.activationGroups; // *** Activate all groups concurrently. *** for (Iterator i = activationGroups.iterator(); i.hasNext();) { ExpansionActivationGroup activationGroup = (ExpansionActivationGroup) i .next(); this.runGroup(activationGroup); } } // runParallel public void doOutput() { // Place tokens on the output expansion nodes. ExpansionRegion region = (ExpansionRegion) this.node; ExpansionNodeList outputElements = region.outputElement; Debug.println("[doOutput] Expansion region " + region.name + " is " + (this.isSuspended() ? "suspended." : "completed.")); if (!this.isSuspended()) { for (int i = 0; i < activationGroups.size(); i++) { ExpansionActivationGroup activationGroup = activationGroups .getValue(i); OutputPinActivationList groupOutputs = activationGroup.groupOutputs; for (int j = 0; j < groupOutputs.size(); j++) { OutputPinActivation groupOutput = groupOutputs.getValue(j); ExpansionNode outputElement = outputElements.getValue(j); this.getExpansionNodeActivation(outputElement).addTokens( groupOutput.takeTokens()); } } } } // doOutput public void terminate() { // Terminate the execution of all contained node activations (which // completes the performance of the expansion region activation). ExpansionActivationGroupList activationGroups = this.activationGroups; for (int i = 0; i < activationGroups.size(); i++) { ExpansionActivationGroup activationGroup = this.activationGroups .getValue(i); OutputPinActivationList groupOutputs = activationGroup.groupOutputs; _beginIsolation(); for (int j = 0; j < groupOutputs.size(); j++) { OutputPinActivation groupOutput = groupOutputs.getValue(j); groupOutput.fire(groupOutput.takeOfferedTokens()); } activationGroup.terminateAll(); _endIsolation(); } super.terminate(); } // terminate public void sendOffers() { // Fire all output expansion nodes and send offers on all outgoing // control flows. ExpansionRegion region = (ExpansionRegion) (this.node); // *** Send offers from all output expansion nodes concurrently. *** ExpansionNodeList outputElements = region.outputElement; for (Iterator i = outputElements.iterator(); i.hasNext();) { ExpansionNode outputElement = (ExpansionNode) i.next(); this.getExpansionNodeActivation(outputElement) .sendUnofferedTokens(); } // Send offers on all outgoing control flows. super.sendOffers(); } // sendOffers public void runGroup( fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionActivationGroup activationGroup) { // Set up the inputs for the group with the given index, run the group // and then fire the group outputs. if (this.isRunning()) { Debug.println("[runGroup] groupInput[0] = " + this.inputExpansionTokens.getValue(0).tokens.getValue(activationGroup.index - 1).getValue()); TokenSetList inputTokens = this.inputTokens; for (int j = 0; j < inputTokens.size(); j++) { TokenSet tokenSet = inputTokens.getValue(j); OutputPinActivation regionInput = activationGroup.regionInputs .getValue(j); regionInput.clearTokens(); regionInput.addTokens(tokenSet.tokens); regionInput.sendUnofferedTokens(); } TokenSetList inputExpansionTokens = this.inputExpansionTokens; for (int j = 0; j < inputExpansionTokens.size(); j++) { TokenSet tokenSet = inputExpansionTokens.getValue(j); OutputPinActivation groupInput = activationGroup.groupInputs .getValue(j); groupInput.clearTokens(); if (tokenSet.tokens.size() >= activationGroup.index) { groupInput.addToken(tokenSet.tokens .getValue(activationGroup.index - 1)); } groupInput.sendUnofferedTokens(); } activationGroup.run(activationGroup.nodeActivations); this.terminateGroup(activationGroup); } } // runGroup public void terminateGroup( fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionActivationGroup activationGroup) { // Terminate the given activation group, after preserving any group // outputs. if (this.isRunning() & !this.isSuspended()) { OutputPinActivationList groupOutputs = activationGroup.groupOutputs; for (int i = 0; i < groupOutputs.size(); i++) { OutputPinActivation groupOutput = groupOutputs.getValue(i); groupOutput.fire(groupOutput.takeOfferedTokens()); } activationGroup.terminateAll(); } } // terminateGroup public fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionNodeActivation getExpansionNodeActivation( fUML.Syntax.Activities.ExtraStructuredActivities.ExpansionNode node) { // Return the expansion node activation corresponding to the given // expansion node, in the context of the activity node activation group // this expansion region activation is in. // [Note: Expansion regions do not own their expansion nodes. Instead, // they are own as object nodes by the enclosing activity or group. // Therefore, they will already be activated along with their expansion // region.] return (ExpansionNodeActivation) (this.group.getNodeActivation(node)); } // getExpansionNodeActivation public int numberOfValues() { // Return the number of values to be acted on by the expansion region of // this activation, which is the minimum of the number of values offered // to each of the input expansion nodes of the activation. ExpansionRegion region = (ExpansionRegion) (this.node); ExpansionNodeList inputElements = region.inputElement; int n = this.getExpansionNodeActivation(inputElements.getValue(0)) .countOfferedValues(); int i = 2; while (i <= inputElements.size()) { int count = this.getExpansionNodeActivation( inputElements.getValue(i - 1)).countOfferedValues(); if (count < n) { n = count; } i = i + 1; } return n; } // numberOfValues public boolean isSuspended() { // Check if the activation group for this node is suspended. boolean suspended = false; int i = 1; while (i <= this.activationGroups.size() & !suspended) { ActivityNodeActivationGroup group = this.activationGroups .get(i - 1); suspended = group.isSuspended(); i = i + 1; } return suspended; } // isSuspended public void resume( fUML.Semantics.Activities.ExtraStructuredActivities.ExpansionActivationGroup activationGroup) { // Resume an expansion region after the suspension of the given // activation group. If the region is iterative, then continue with the // iteration. If the region is parallel, and there are no more suspended // activation groups, then generate the expansion node output. ExpansionRegion region = (ExpansionRegion) this.node; this.resume(); this.terminateGroup(activationGroup); if (region.mode == ExpansionKind.iterative) { this.runIterative(); } this.doOutput(); } // resume } // ExpansionRegionActivation