Issue 17209: Error handling creation and destruction of links of associations with ordered ends (fuml-rtf) Source: Model Driven Solutions (Mr. Ed Seidewitz, ed-s(at)modeldriven.com) Nature: Uncategorized Issue Severity: Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-01) Subclause: 8.3.2.2.11 Link The behavior of the Link::setFeatureValue operation results in the FeatureValues for an ordered end to be totally ordered by “position” across all links of an association. However, when a new link is created, the insertAt position for an ordered end isn’t relative to all links but only relative to links for which the other ends have the same values as the link being created. This means that the FeatureValues of the ordered ends of the new link may not be inserted at the correct position. Resolution: agreed Revised Text: In Subclause 8.5.2.2.11 and Figure 8.12, add the following operations to the Link class: • isMatchingLink(link: ExtensionalValue, end: Property): Boolean // Test whether the given link matches the values of this link on all // ends other than the given end. PropertyList ends = this.type.memberEnd; boolean matches = true; int i = 1; while (matches & i <= ends.size()) { Property otherEnd = ends.getValue(i - 1); if (otherEnd != end & !this.getFeatureValue(otherEnd).values.getValue(0).equals( link.getFeatureValue(otherEnd).values.getValue(0))) { matches = false; } i = i + 1; } return matches; • getOtherFeatureValues(extent: ExtensionalValue[*], end: Property) // Return all feature values for the given end of links in the given // extent whose other ends match this link. FeatureValueList featureValues = new FeatureValueList(); for (int i = 0; i < extent.size(); i++) { ExtensionalValue link = extent.getValue(i); if (link != this) { if (isMatchingLink(link, end)) { featureValues.addValue(link.getFeatureValue(end)); } } } return featureValues; • addTo(locus: Locus) // Add this link to the extent of its association at the given locus. // Shift the positions of ends of other links, as appropriate, for ends // that are ordered. Debug.println("[addTo] link = " + this.objectId()); PropertyList ends = this.type.memberEnd; ExtensionalValueList extent = locus.getExtent(this.type); for (int i = 0; i < ends.size(); i++) { Property end = ends.getValue(i); if (end.multiplicityElement.isOrdered) { FeatureValue featureValue = this.getFeatureValue(end); FeatureValueList otherFeatureValues = this.getOtherFeatureValues(extent, end); int n = otherFeatureValues.size(); if (featureValue.position < 0 | featureValue.position > n) { featureValue.position = n + 1; } else { if (featureValue.position == 0) { featureValue.position = 1; } for (int j = 0; j < otherFeatureValues.size(); j++) { FeatureValue otherFeatureValue = featureValues.getValue(j); if (featureValue.position <= otherFeatureValue.position) { otherFeatureValue.position = otherFeatureValue.position + 1; } } } } } locus.add(this); Remove the (overriding) operation getFeatureValue. In Subclause 8.6.3.2.1 AddStructuralFeatureValueActionActivation, in operation doAction, replace the “else” part of the if statement beginning “if (action.isReplaceAll)” with: if (feature.multiplicityElement.isUnique) { int i = 1; boolean destroyed = false; while (!destroyed & i <= links.size()) { Link link = links.getValue(i - 1); FeatureValue featureValue = link.getFeatureValue(feature); if (featureValue.values.getValue(0).equals(inputValue)) { position = link.getFeatureValue(oppositeEnd).position; link.destroy(); destroyed = true; } i = i + 1; } } Subsequently in the code, remove the lines // This necessary when setting a feature value with an insertAt position newLink.locus = this.getExecutionLocus(); and replace the statement newLink.locus.add(newlink); with: newlink.addTo(this.getExecutionLocus()); Finally, remove the statement: if (insertAt > 0 & j < insertAt) { insertAt = insertAt - 1; } In Subclause 8.6.3.2.4 CreateLinkActionActivation, in operation doAction, replace the code starting at the comment “// This necessary when setting a feature value with an insertAt position” to the end of the operation with: for (int i = 0; i < endDataList.size(); i++) { LinkEndCreationData endData = endDataList.getValue(i); int insertAt = 0; if (endData.insertAt != null) { insertAt = ((UnlimitedNaturalValue) (this .takeTokens(endData.insertAt).getValue(0))).value.naturalValue; } newLink.setFeatureValue(endData.end, this.takeTokens(endData.value), insertAt); } newLink.addTo(this.getExecutionLocus()); Actions taken: March 3, 2012: received issue January 7, 2013: closed issue Discussion: End of Annotations:===== m: Ed Seidewitz To: "issues@omg.org" Subject: Error handling creation and destruction of links of associations with ordered ends Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-01) Subclause: 8.3.2.2.11 Link The behavior of the Link::setFeatureValue operation results in the FeatureValues for an ordered end to be totally ordered by .position. across all links of an association. However, when a new link is created, the insertAt position for an ordered end isn.t relative to all links but only relative to links for which the other ends have the same values as the link being created. This means that the FeatureValues of the ordered ends of the new link may not be inserted at the correct position.