FUML 1.0b2 NO IDEA Avatar
  1. OMG Issue

FUML — 8.6.2.2.1 ActionActivation, 8.6.3.2.4 CreateLinkActionActivation and 8.6.3.2.8 LinkActionActivation

  • Key: FUML-29
  • Legacy Issue Number: 13873
  • Status: closed  
  • Source: NASA ( Dr. Nicolas F. Rouquette)
  • Summary:

    Specification: Semantics of a Foundation Subset for Executable UML Models, FTF – Beta 1 (ptc/08-11-03)

    Section: 8.6.2.2.1 ActionActivation, 8.6.3.2.4 CreateLinkActionActivation and 8.6.3.2.8 LinkActionActivation

    Depends on: http://www.omg.org/issues/fuml-ftf.html#Issue13544

    Summary:

    Part of CreateLinkActionActivation.doAction() entails destroying all links that have a value for any end for which isReplaceAll is true. (see fUML 1.0, page 238). This involves the following chain of invocations:

    • fUML.Semantics.Actions.IntermediateActions.LinkActionActivation.endMatchesEndData(Link, LinkEndData) – see fUML 1.0, page 238;
    • fUML.Semantics.Actions.BasicActions.ActionActivation.getTokens(InputPin) – see fUML 1.0, page 233;
    • fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivation.takeTokens() – see fUML 1.0, p. 215

    By taking the tokens from the pin activation corresponding to the input pin, LinkActionActivation.endMatchesEndData() induces side effects on the state of the execution engine each time it is called.

    Proposed Resolution:

    Resolving this issue entails 3 things:

    a) Defining a read-only operation to read the tokens available on an input pin:

    fUML.Semantics.Actions.BasicActions.ActionActivation.readTokens(InputPin)

    /**

    • NFR 04/16/2009 For LinkActionActivation.endMatchesEndData(Link, LinkEndData),
    • we need a mechanism to test whether the available tokens match the link end data
    • and if they do, then actually remove them.
    • readTokens() is the same as getTokens() except that:
    • getTokens() removes the tokens on the pin activation, i.e, pinActivation.takeTokens()
    • readTokens() leaves the tokens on the pin activation, i.e., pinActivation.getTokens()
    • @param pin
    • @return

    */

    public fUML.Semantics.Classes.Kernel.ValueList readTokens(

    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.

    // NFR 04/16/2009

    Debug.println("[readTokens] node = " + this.node.name + " (pin: " + pin.name + ")");

    PinActivation pinActivation = this.getPinActivation(pin);

    TokenList tokens = pinActivation.getTokens();

    ValueList values = new ValueList();

    for (int i = 0; i < tokens.size(); i++) {

    Token token = tokens.getValue;

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

    if (value != null)

    { values.addValue(value); }

    }

    return values;

    }

    b) With the above operation, LinkActionActivation.endMatchesEndData() can be fixed as follows:

    public boolean endMatchesEndData(fUML.Semantics.Classes.Kernel.Link link,

    fUML.Syntax.Actions.IntermediateActions.LinkEndData endData) {

    // Test whether the appropriate end of the given link matches the given

    // end data.

    boolean matches = false;

    if (endData.value == null)

    { matches = true; }

    else {

    Property end = endData.end;

    FeatureValue linkFeatureValue = link.getFeatureValue(end);

    Value endValue = this.readTokens(endData.value).getValue(0);

    if (endData instanceof LinkEndDestructionData) {

    if (!((LinkEndDestructionData) endData).isDestroyDuplicates

    & !end.multiplicityElement.isUnique & end.multiplicityElement.isOrdered)

    { int destroyAt = ((UnlimitedNaturalValue) (this .readTokens(((LinkEndDestructionData) endData).destroyAt).getValue(0))).value.naturalValue; matches = linkFeatureValue.values.getValue(0).equals(endValue) && linkFeatureValue.position == destroyAt; }

    else

    { matches = linkFeatureValue.values.getValue(0).equals(endValue); }

    } else

    { matches = linkFeatureValue.values.getValue(0).equals(endValue); }

    }

    return matches;

    }

    c) All other actions/activity behaviors which directly or indirectly invoked LinkActionActivation.endMatchesEndData() need to be reviewed to make sure that the tokens will be consumed. There are only 3 cases to consider:

    fUML.Semantics.Actions.IntermediateActions.CreateLinkActionActivation.doAction()

    fUML.Semantics.Actions.IntermediateActions.DestroyLinkActionActivation.doAction()

    fUML.Semantics.Actions.IntermediateActions.ReadLinkActionActivation.doAction()

    CreateLinkActionActivation.doAction() already consumes the tokens when creating the new link instance.

    DestroyLinkActionActivation.doAction() needs extra logic to delete the tokens from the input pins after determining the matching links to destroy, if any. This requires modifying this operation as follows:

    public void doAction() {

    // Get the extent, at the current execution locus, of the association

    // for which links are being destroyed.

    // Destroy all links that match the given link end destruction data.

    // For unique ends, or non-unique ends for which isDestroyDuplicates is

    // true, match links with a matching value for that end.

    // For non-unique, ordered ends for which isDestroyDuplicates is false,

    // match links with an end value at the given destroyAt position. [Must

    // a value be given, too, in this case?]

    // For non-unique, non-ordered ends for which isDestroyDuplicates is

    // false, pick one matching link (if any) non-deterministically. [The

    // semantics of this case is not clear from the current spec.]

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

    LinkEndDestructionDataList destructionDataList = action.endData;

    boolean destroyOnlyOne = false;

    int j = 1;

    while (!destroyOnlyOne & j <= destructionDataList.size())

    { LinkEndDestructionData endData = destructionDataList.getValue(j - 1); destroyOnlyOne = !endData.end.multiplicityElement.isUnique & !endData.end.multiplicityElement.isOrdered & !endData.isDestroyDuplicates; j = j + 1; }

    LinkEndDataList endDataList = new LinkEndDataList();

    for (int i = 0; i < destructionDataList.size(); i++)

    { LinkEndDestructionData endData = destructionDataList.getValue(i); endDataList.addValue(endData); }

    ExtensionalValueList extent = this.getExecutionLocus().getExtent(this.getAssociation());

    ExtensionalValueList matchingLinks = new ExtensionalValueList();

    for (int i = 0; i < extent.size(); i++) {

    ExtensionalValue value = extent.getValue;

    Link link = (Link) value;

    if (this.linkMatchesEndData(link, endDataList))

    { matchingLinks.addValue(link); }

    }

    /*

    • NFR 04/16/2009
    • Now that we know which matching links to destroy,
    • we need to ensure all of the tokens on the input pins
    • of this action are consumed.

    */

    for (int i = 0; i < destructionDataList.size(); i++) {

    LinkEndDestructionData endData = destructionDataList.getValue;

    Property end = endData.end;

    if (!endData.isDestroyDuplicates

    & !end.multiplicityElement.isUnique & end.multiplicityElement.isOrdered)

    { this.getTokens(endData.destroyAt); }

    this.getTokens(endData.value);

    }

    if (destroyOnlyOne) {

    // *** If there is more than one matching link,

    // non-deterministically choose one. ***

    if (matchingLinks.size() > 0)

    { int i = ((ChoiceStrategy) this.getExecutionLocus().factory.getStrategy("choice")) .choose(matchingLinks.size()); matchingLinks.getValue(i - 1).destroy(); }

    } else {

    for (int i = 0; i < matchingLinks.size(); i++)

    { ExtensionalValue matchingLink = matchingLinks.getValue(i); matchingLink.destroy(); }

    }

    }

    ReadLinkActionActivation.doAction() needs extra logic to consume the tokens after matching the data against all of the links in the extension.

    public void doAction() {

    // Get the extent, at the current execution locus, of the association to

    // which the action applies.

    // For all links that match the link end data, place the value of the

    // remaining "open" end on the result pin.

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

    LinkEndDataList endDataList = action.endData;

    LinkEndData openEnd = null;

    int i = 1;

    while ((openEnd == null) & i <= endDataList.size()) {

    if (endDataList.getValue(i-1).value == null)

    { openEnd = endDataList.getValue(i-1); }

    i = i + 1;

    }

    ExtensionalValueList extent = this.getExecutionLocus().getExtent(this.getAssociation());

    for (int j = 0; j < extent.size(); j++) {

    ExtensionalValue value = extent.getValue(j);

    Link link = (Link) value;

    if (this.linkMatchesEndData(link, endDataList))

    { Value resultValue = link.getFeatureValue(openEnd.end).values.getValue(0); this.putToken(action.result, resultValue); }

    }

    /*

    • NFR 04/16/2009
    • Now that we have checked all links for possible matches,
    • we have to consume the tokens on the input pins corresponding to the non-open link ends.

    */

    for (int k=0; k<endDataList.size(); k++) {

    LinkEndData endData = endDataList.getValue(k);

    if (endData.value != null)

    { this.getTokens(endData.value); }

    }

    }

  • Reported: FUML 1.0b1 — Thu, 16 Apr 2009 04:00 GMT
  • Disposition: Resolved — FUML 1.0b2
  • Disposition Summary:

    Part of the problem is that the name for ActionActivation::getTokens is inconsistent with the names of other operations in the execution model, where “get” is used for operations that do not consume tokens while “take” is used for operations that do. Therefore, it makes sense to change the name of the current “getTokens” operation to “takeTokens” and use the name “getTokens” for the new operation (rather than “readTokens”, as proposed). Also, to be consistent with the resolution to issue 13310, the new operation should call pinActivation.getUnofferedTokens(), rather than pinActivation.getTokens().
    Other than this, the rest of the proposed resolution is accepted.

  • Updated: Fri, 6 Mar 2015 20:58 GMT