/* * 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.Actions.IntermediateActions; 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.Actions.BasicActions.*; import fUML.Syntax.Actions.IntermediateActions.*; 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.LociL1.*; public class DestroyLinkActionActivation extends fUML.Semantics.Actions.IntermediateActions.WriteLinkActionActivation { 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.] Debug.println("[doAction] DestroyLinkAction..."); DestroyLinkAction action = (DestroyLinkAction) (this.node); LinkEndDestructionDataList destructionDataList = action.endData; Debug.println("[doAction] end data size = " + destructionDataList.size()); 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); Debug.println("[doAction] Matching end = " + endData.end.name); 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(i); Link link = (Link) value; if (this.linkMatchesEndData(link, endDataList)) { matchingLinks.addValue(link); } } // Now that matching is done, ensure that all tokens on end data input // pins // are consumed. for (int i = 0; i < destructionDataList.size(); i++) { LinkEndDestructionData endData = destructionDataList.getValue(i); Property end = endData.end; if (!endData.isDestroyDuplicates & !end.multiplicityElement.isUnique & end.multiplicityElement.isOrdered) { this.takeTokens(endData.destroyAt); } Debug.println("[doAction] Consuming tokens for end " + end.name); this.takeTokens(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(); } } } // doAction } // DestroyLinkActionActivation