All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fUML.Semantics.Actions.BasicActions.ActionActivation Maven / Gradle / Ivy

Go to download

This open source software is a reference implementation, consisting of software and related files, for the OMG specification called the Semantics of a Foundational Subset for Executable UML Models (fUML). The reference implementation is intended to implement the execution semantics of UML activity models, accepting an XMI file from a conformant UML model as its input and providing an execution trace of the selected activity model(s) as its output. The core execution engine, which is directly generated from the normative syntactic and semantic models for fUML, may also be used as a library implementation of fUML in other software.

There is a newer version: 1.5.0a
Show newest version

/*
 * Initial version copyright 2008 Lockheed Martin Corporation, except  
 * as stated in the file entitled Licensing-Information. 
 * 
 * All modifications copyright 2009-2017 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.Actions.BasicActions;

import fUML.Debug;
import UMLPrimitiveTypes.*;

import java.util.*;

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.Actions.BasicActions.*;
import fUML.Semantics.*;
import fUML.Semantics.Classes.Kernel.*;
import fUML.Semantics.CommonBehaviors.BasicBehaviors.*;
import fUML.Semantics.Activities.IntermediateActivities.*;
import fUML.Semantics.Loci.*;

public abstract class ActionActivation extends
		fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivation {

	public fUML.Semantics.Actions.BasicActions.PinActivationList pinActivations = new fUML.Semantics.Actions.BasicActions.PinActivationList();
	public boolean firing = false;
	
	public void initialize(ActivityNode node, ActivityNodeActivationGroup group) {
		// Initialize this action activation to be not firing.
		
		super.initialize(node, group);
		this.firing = false;
	}

	public void run() {
		// Run this action activation and any outoging fork node attached to it.

		super.run();

		if (this.outgoingEdges.size() > 0) {
			this.outgoingEdges.getValue(0).target.run();
		}

		this.firing = false;
	} // run

	public fUML.Semantics.Activities.IntermediateActivities.TokenList takeOfferedTokens() {
		// If the action is not locally reentrant, then mark this activation as
		// firing.
		// Take any incoming offers of control tokens, then concurrently fire
		// all input pin activations.

		// Note: This is included here to happen in the same isolation scope as
		// the isReady test.
		this.firing = !((Action) this.node).isLocallyReentrant;

		TokenList offeredTokens = new TokenList();

		ActivityEdgeInstanceList incomingEdges = this.incomingEdges;
		for (int i = 0; i < incomingEdges.size(); i++) {
			ActivityEdgeInstance incomingEdge = incomingEdges.getValue(i);
			TokenList tokens = incomingEdge.takeOfferedTokens();
			for (int j = 0; j < tokens.size(); j++) {
				Token token = tokens.getValue(j);
				token.withdraw();
				offeredTokens.addValue(token);
			}
		}

		Action action = (Action) (this.node);

		// *** Fire all input pins concurrently. ***
		InputPinList inputPins = action.input;
		for (Iterator i = inputPins.iterator(); i.hasNext();) {
			InputPin pin = (InputPin) (i.next());
			PinActivation pinActivation = this.getPinActivation(pin);
			TokenList tokens = pinActivation.takeOfferedTokens();
			pinActivation.fire(tokens);
			for (int j = 0; j < tokens.size(); j++) {
				Token token = tokens.getValue(j);
				offeredTokens.addValue(token);
			}
		}

		return offeredTokens;
	} // takeOfferedTokens

	public void fire(
			fUML.Semantics.Activities.IntermediateActivities.TokenList incomingTokens) {
		// Do the main action behavior then concurrently fire all output pin
		// activations
		// and offer a single control token. Then activate the action again,
		// if it is still ready to fire and has at least one token actually
		// being
		// offered to it.

		do {

			Debug.println("[fire] Action " + this.node.name + "...");
			Debug.println("[event] Fire activity="
					+ this.getActivityExecution().getBehavior().name
					+ " action=" + this.node.name);

			this.doAction();
			incomingTokens = this.completeAction();

		} while (incomingTokens.size() > 0);
	} // fire

	public void terminate() {
		// Terminate this action activation and any outgoing fork node attached
		// to it.

		super.terminate();

		if (this.outgoingEdges.size() > 0) {
			this.outgoingEdges.getValue(0).target.terminate();
		}
	} // terminate

	public fUML.Semantics.Activities.IntermediateActivities.TokenList completeAction() {
		// Concurrently fire all output pin activations and offer a single
		// control token. Then check if the action should fire again
		// and, if so, return additional incoming tokens for this.

		this.sendOffers();

		Debug.println("[fire] Checking if " + this.node.name + " should fire again...");

		_beginIsolation();
		TokenList incomingTokens = new TokenList();
		this.firing = false;
		if (this.isReady()) {
			incomingTokens = this.takeOfferedTokens();
			this.firing = this.isFiring() & incomingTokens.size() > 0;
		}
		_endIsolation();

		return incomingTokens;
	} // completeAction

	public boolean isReady() {
		// In addition to the default condition, check that, if the action has
		// isLocallyReentrant=false, then the activation is not currently
		// firing,
		// and that the sources of all incoming edges (control flows) have
		// offers and all input pin activations are ready.
		// [This assumes that all edges directly incoming to the action are
		// control flows.]

		boolean ready = super.isReady()
				& (((Action) this.node).isLocallyReentrant | !this.isFiring());

		int i = 1;
		while (ready & i <= this.incomingEdges.size()) {
			ready = this.incomingEdges.getValue(i - 1).hasOffer();
			i = i + 1;
		}

		InputPinList inputPins = ((Action) (this.node)).input;
		int j = 1;
		while (ready & j <= inputPins.size()) {
			ready = this.getPinActivation(inputPins.getValue(j - 1)).isReady();
			j = j + 1;
		}

		return ready;
	} // isReady

	public boolean isFiring() {
		// Indicate whether this action activation is currently firing or not.

		return firing;
	} // isFiring

	public abstract void doAction();

	public void sendOffers() {
		// Fire all output pins and send offers on all outgoing control flows.

		Action action = (Action) (this.node);

		// *** Send offers from all output pins concurrently. ***
		OutputPinList outputPins = action.output;
		for (Iterator i = outputPins.iterator(); i.hasNext();) {
			OutputPin outputPin = (OutputPin) i.next();
			PinActivation pinActivation = this.getPinActivation(outputPin);
			pinActivation.sendUnofferedTokens();
		}

		// Send offers on all outgoing control flows.
		if (this.outgoingEdges.size() > 0) {
			TokenList tokens = new TokenList();
			tokens.addValue(new ControlToken());
			this.addTokens(tokens);
			this.outgoingEdges.getValue(0).sendOffer(tokens);
		}
	} // sendOffers

	public void createNodeActivations() {
		// Create node activations for the input and output pins of the action
		// for this activation.
		// [Note: Pins are owned by their actions, not by the enclosing activity
		// (or group), so they must be activated through the action activation.]

		Action action = (Action) (this.node);

		ActivityNodeList inputPinNodes = new ActivityNodeList();
		InputPinList inputPins = action.input;
		for (int i = 0; i < inputPins.size(); i++) {
			InputPin inputPin = inputPins.getValue(i);
			inputPinNodes.addValue(inputPin);
		}

		this.group.createNodeActivations(inputPinNodes);

		for (int i = 0; i < inputPinNodes.size(); i++) {
			ActivityNode node = inputPinNodes.getValue(i);
			this.addPinActivation((PinActivation) (this.group
					.getNodeActivation(node)));
		}

		ActivityNodeList outputPinNodes = new ActivityNodeList();
		OutputPinList outputPins = action.output;
		for (int i = 0; i < outputPins.size(); i++) {
			OutputPin outputPin = outputPins.getValue(i);
			outputPinNodes.addValue(outputPin);
		}

		this.group.createNodeActivations(outputPinNodes);

		for (int i = 0; i < outputPinNodes.size(); i++) {
			ActivityNode node = outputPinNodes.getValue(i);
			this.addPinActivation((PinActivation) (this.group
					.getNodeActivation(node)));
		}
	} // createNodeActivations

	public void addOutgoingEdge(
			fUML.Semantics.Activities.IntermediateActivities.ActivityEdgeInstance edge) {
		// If there are no outgoing activity edge instances, create a single
		// activity edge instance with a fork node execution at the other end.
		// Add the give edge to the fork node execution that is the target of
		// the activity edge instance out of this action execution.
		// [This assumes that all edges directly outgoing from the action are
		// control flows, with an implicit fork for offers out of the action.]

		ActivityNodeActivation forkNodeActivation;

		if (this.outgoingEdges.size() == 0) {
			forkNodeActivation = new ForkNodeActivation();
			forkNodeActivation.running = false;
			ActivityEdgeInstance newEdge = new ActivityEdgeInstance();
			super.addOutgoingEdge(newEdge);
			forkNodeActivation.addIncomingEdge(newEdge);
		} else {
			forkNodeActivation = this.outgoingEdges.getValue(0).target;
		}

		forkNodeActivation.addOutgoingEdge(edge);
	} // addOutgoingEdge

	public void addPinActivation(
			fUML.Semantics.Actions.BasicActions.PinActivation pinActivation) {
		// Add a pin activation to this action activation.

		this.pinActivations.addValue(pinActivation);
		pinActivation.actionActivation = this;
	} // addPinActivation

	public fUML.Semantics.Actions.BasicActions.PinActivation getPinActivation(
			fUML.Syntax.Actions.BasicActions.Pin pin) {
		// Precondition: The given pin is owned by the action of the action
		// activation.
		// Return the pin activation corresponding to the given pin.

		PinActivation pinActivation = null;
		int i = 1;
		while (pinActivation == null & i <= this.pinActivations.size()) {
			PinActivation thisPinActivation = this.pinActivations
					.getValue(i - 1);
			if (thisPinActivation.node == pin) {
				pinActivation = thisPinActivation;
			}
			i = i + 1;
		}

		return pinActivation;

	} // getPinActivation

	public void putToken(fUML.Syntax.Actions.BasicActions.OutputPin pin,
			fUML.Semantics.Classes.Kernel.Value value) {
		// Precondition: The action execution has fired and the given pin is
		// owned by the action of the action execution.
		// Place a token for the given value on the pin activation corresponding
		// to the given output pin.

		Debug.println("[putToken] node = " + this.node.name);

		ObjectToken token = new ObjectToken();
		token.value = value;

		PinActivation pinActivation = this.getPinActivation(pin);
		pinActivation.addToken(token);
	} // putToken

	public void putTokens(fUML.Syntax.Actions.BasicActions.OutputPin pin,
			fUML.Semantics.Classes.Kernel.ValueList values) {
		// Precondition: The action execution has fired and the given pin is
		// owned by the action of the action execution.
		// Place tokens for the given values on the pin activation corresponding
		// to the given output pin.

		// Debug.println("[putTokens] node = " + this.node.name);

		for (int i = 0; i < values.size(); i++) {
			Value value = values.getValue(i);
			this.putToken(pin, value);
		}

	} // putTokens

	public fUML.Semantics.Classes.Kernel.ValueList getTokens(
			fUML.Syntax.Actions.BasicActions.InputPin pin) {
		// Precondition: The action execution has fired and the given pin is
		// owned by the action of the action execution.
		// Get any tokens held by the pin activation corresponding to the given
		// input pin and return them
		// (but leave the tokens on the pin).

		Debug.println("[getTokens] node = " + this.node.name + ", pin = " + pin.name);

		PinActivation pinActivation = this.getPinActivation(pin);
		TokenList tokens = pinActivation.getUnofferedTokens();

		ValueList values = new ValueList();
		for (int i = 0; i < tokens.size(); i++) {
			Token token = tokens.getValue(i);
			Value value = ((ObjectToken) token).value;
			if (value != null) {
				values.addValue(value);
			}
		}

		return values;
	} // getTokens

	public fUML.Semantics.Classes.Kernel.ValueList takeTokens(
			fUML.Syntax.Actions.BasicActions.InputPin pin) {
		// Precondition: The action execution has fired and the given pin is
		// owned by the action of the action execution.
		// Take any tokens held by the pin activation corresponding to the given
		// input pin and return them.

		Debug.println("[takeTokens] node = " + this.node.name + ", pin = " + pin.name);

		PinActivation pinActivation = this.getPinActivation(pin);
		TokenList tokens = pinActivation.takeUnofferedTokens();

		ValueList values = new ValueList();
		for (int i = 0; i < tokens.size(); i++) {
			Token token = tokens.getValue(i);
			Value value = ((ObjectToken) token).value;
			if (value != null) {
				values.addValue(value);
			}
		}

		return values;
	} // takeTokens

	public boolean isSourceFor(
			fUML.Semantics.Activities.IntermediateActivities.ActivityEdgeInstance edgeInstance) {
		// If this action has an outgoing fork node, check that the fork node is
		// the source of the given edge instance.

		boolean isSource = false;
		if (this.outgoingEdges.size() > 0) {
			isSource = this.outgoingEdges.getValue(0).target
					.isSourceFor(edgeInstance);
		}

		return isSource;
	} // isSourceFor

	public boolean valueParticipatesInLink(
			fUML.Semantics.Classes.Kernel.Value value,
			fUML.Semantics.Classes.Kernel.Link link) {
		// Test if the given value participates in the given link.

		FeatureValueList linkFeatureValues = link.getFeatureValues();

		boolean participates = false;
		int i = 1;
		while (!participates & i <= linkFeatureValues.size()) {
			participates = linkFeatureValues.getValue(i - 1).values.getValue(0)
					.equals(value);
			i = i + 1;
		}

		return participates;
	} // valueParticipatesInLink

	public fUML.Semantics.Classes.Kernel.BooleanValue makeBooleanValue(
			boolean value) {
		// Make a Boolean value using the built-in Boolean primitive type.
		// [This ensures that Boolean values created internally are the same as
		// the default used for evaluating Boolean literals.]

		LiteralBoolean booleanLiteral = new LiteralBoolean();
		booleanLiteral.value = value;
		return (BooleanValue) (this.getExecutionLocus().executor
				.evaluate(booleanLiteral));
	} // makeBooleanValue

} // ActionActivation




© 2015 - 2025 Weber Informatics LLC | Privacy Policy