Issues for Mailing list of the Semantics of a Foundational Subset for Executable UML Models 1.1 (fUML) RTF
To comment on any of these issues, send email to fuml-rtf@omg.org. (Please include the issue number in the Subject: header, thusly: [Issue ###].) To submit a new issue, send email to issues@omg.org.
List of issues (green=resolved, yellow=pending Board vote, red=unresolved)
Issue 13872: 7.4.2.2.2 ActivityEdge, 7.4.2.2.4 ActivityNode & A.5.2 List Add
Issue 14526: Flow final nodes should be included
Issue 15130: An action may not stop firing again
Issue 15986: fUML 1.1 should be based on UML 2.4
Issue 15987: The fUML Foundational Model Library should support the new UML 2.4 Real primitive type
Issue 16654: Error in ExpansionRegionActivation::takeOfferedTokens
Issue 16686: Error in CreateLinkAction semantics
Issue 16687: Duplicate code for ActionActivation::putToken
Issue 16948: Error in DecisionNodeActivation semantics
Issue 17168: Spurious comment on operation PinActivation::fire
Issue 17200: Error in RemoveStructuralFeatureVauleActionActivation::doAction
Issue 17201: Bug in DestroyObjectActivation::objectIsComposite
Issue 17203: Bug in ForkedToken::withdraw when the baseToken is a ForkedToken
Issue 17205: Error in ActivityNodeActivationGroup::getOutputParameterNodeActivations
Issue 17209: Error handling creation and destruction of links of associations with ordered ends
Issue 17211: ExecutionFactoryL2::instantiateVistor duplicates code from ExecutionFactorL3::instatiateVistor
Issue 17213: ActionActivation.sendOffers(): Missing sending of offers on outgoing control flows?
Issue 17270: Structural Feature Actions on Data Values Need to Create a new Result Value
Issue 17282: Error in check for enable nodes
Issue 17288: ExpansionRegionActivation does not reset its activationGroups
Issue 17291: ForkNodeActivation does not clear its tokens on termination
Issue 17298: ExpansionRegionActivation isReady condition is too strong
Issue 17299: LoopNodeActivation does not properly handle termination due to an activity final node
Issue 17300: An activity final node should not fire if it is not offered any tokens
Issue 17311: Having a fork node as initial enabled node does not work
Issue 17312: DecisionNodeActivation can send offers to multiple outgoing edges
Issue 17314: Structured activity node activations do not wait for contained accept event action activations
Issue 17345: Correction to the resolution of Issue 17209
Issue 17346: Read link actions and read structural feature actions do not handle ordered ends correctly
Issue 17391: Error in setting result pin values for CallActions
Issue 17392: Addition to resolution to Issue 17299
Issue 17396: Errors in ReduceActionActivation::doAction
Issue 17397: Null tokens are not sent on by control nodes
Issue 17499: Conditional node and loop node activations do not wait for contained accept event action activations
Issue 17502: Specification of ClassifierBehaviorExecution and ObjectActivation are not consistent with Annex A
Issue 17557: Addition to the resolution to fUML Issue 15987
Issue 17558: Addition to the resolution of fUML Issue 17203
Issue 17559: Correction to the resolution to fUML Issue 17209
Issue 17560: Addition to the resolution to fUML Issue 17499
Issue 13872: 7.4.2.2.2 ActivityEdge, 7.4.2.2.4 ActivityNode & A.5.2 List Add (fuml-rtf)
Click here for this issue's archive.
Source: NASA (Dr. Nicolas F. Rouquette, nicolas.f.rouquette(at)jpl.nasa.gov)
Nature: Uncategorized Issue
Severity:
Summary:
Specification: Semantics of a Foundation Subset for Executable UML Models, FTF – Beta 1 (ptc/08-11-03)
Section: 7.4.2.2.2 ActivityEdge, 7.4.2.2.4 ActivityNode & A.5.2 List Add
Summary:
The fUML execution engine in clause 8 and the fUML reference implementation [1] are both written according to the Java => bUML mapping specified in appendix A of the fUML specification.
Unfortunately, this Java => bUML mapping does not take into account the different kinds of containers used fUML because the ListAdd operation (A.5.2) is defined to be the Java equivalent of fUML AddStructuralFeature Value {isReplaceAll=false}.
This creates a problem in several places where fUML class attributes are defined to be unique; in particular:
7.4.2.2.2 ActivityEdge::source {unique}
7.4.2.2.2 ActivityEdge::target {unique}
7.4.2.2.4 ActivityNode::incoming {unique}
7.4.2.2.4 ActivityNode::outgoing {unique}
The fUML reference implementation [1] loads an fUML model by CMOF reflection.
This means that it processes each activity edge in three parts:
1. The activity node at the source of the edge
2. The activity node at the target of the edge
3. The edge itself
#1 and #3 lead to a duplication of the same edge on the outgoing list of the source node.
#2 and #3 lead to a duplication of the same edge on the incoming list of the target node.
[1] http://portal.modeldriven.org/content/foundational-uml-reference-implementation
Proposed resolution:
The fUML specification should update the Java => bUML mapping to account for the different kinds of containers used for fUML.
The fUML reference implementation should be updated according to the revised Java => bUML mapping for collections.
A workaround to this issue for the reference implementation in [1] involves modifying fUML.Syntax.Activities.IntermediateActivities.ActivityEdge as follows:
public void setTarget(fUML.Syntax.Activities.IntermediateActivities.ActivityNode target) {
this.target = target;
/**
* NFR 04/15/2009
* Because the reference implementation "constructs" the fUML.Syntax model by reflection from the XMI,
* it turns out that activity edges get a duplication of their source pins because:
* - once by reflection when creating the ActivityNode whose .incoming edges includes this instance.
* - a second time this ActivityEdge is constructed by reflection.
*/
if (!target.incoming.contains(this)) {
target.incoming.addValue(this);
} else {
Debug.println("ActivityEdge[" + this.name + "].setTarget(target) this edge is already included in the incoming edge list for target: " + target.getClass().getCanonicalName()+"[" + target.name + "]");
}
}
public void setSource(fUML.Syntax.Activities.IntermediateActivities.ActivityNode source) {
this.source = source;
/**
* NFR 04/15/2009
* Because the reference implementation "constructs" the fUML.Syntax model by reflection from the XMI,
* it turns out that activity edges get a duplication of their source pins because:
* - once by reflection when creating the ActivityNode whose .outgoing edges includes this instance.
* - a second time this ActivityEdge is constructed by reflection.
*/
if (! source.outgoing.contains(this)) {
source.outgoing.addValue(this);
} else {
Debug.println("ActivityEdge[" + this.name + "].setSource(target) this edge is already included in the outgoing edge list for target: " + source.getClass().getCanonicalName()+"[" + source.name + "]");
}
}
Resolution: This issue seems to be a problem with a specific implementation of fUML, not with the fUML specification itself. The uniqueness of association ends is essentially a constraint that there are no duplicate values on that end. fUML only gives semantics to syntactically valide models for which all well-formedness constraints are satisfied, including implicit constraints like multiplicity and uniqueness, as well as constraints given explicitly in OCL. Any implementation that violates syntactic constraints when loading a model is simply an incorrect implementation. It is not necessary to further complicate the fUML semantic specification or the Java=>bUML mapping to account for this.
Revised Text: None
Disposition: Closed, No Change
Revised Text:
Actions taken:
April 16, 2009: received issue
January 7, 2013: closed issue
Discussion: The FTF agrees that this is a problem that needs fixing but, due to lack of time, decided to defer its resolution to a future RTF working on this specification.
Revised Text:
None.
Disposition: Deferred
Issue 14526: Flow final nodes should be included (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (ptc/2008-11-03)
Subclause: 7.4.2 IntermediateActivities
Flow final nodes are currently excluded from the fUML subset. However, such nodes can be useful to explicitly consume tokens without terminating an activity. Since their semantics would be very easy to add to the execution model, it should be considered to add them to the fUML subset
Resolution: Agreed.
Revised Text: In Subclause 7.4.2.1 Overview, remove the following paragraphs:
From Control Nodes (see Figure 7.22):
• FlowFinalNode. Flow final nodes are not included in fUML because it is generally not necessary to explicitly terminate an individual flow in an activity. (Activity final nodes are included in fUML in order to terminate the entire activity.)
In Figure 7.22, Control Nodes, add the following class as a subclass of FinalNode:
FlowFinalNode
After Subclause 7.4.2.2.9 FinalNode, insert the following subclause (and renumber subsequent subclauses appropriately).
7.4.2.2.10 FlowFinalNode
Generalizations
• “FinalNode” on page 57
Attributes
None
Associations
None
Additional Constraints
None
In Subclause 8.2.3.2.1 ExecutionFactoryL2, in the instantiateVistor operation (as corrected by the resolution to Issue 17211), after the lines
else if (element instanceof ActivityFinalNode) {
visitor = new ActivityFinalNodeActivation();
}
add the lines
else if (element instanceof FlowFinalNode) {
visitor = new FlowFinalNodeActivation();
}
In Subclause 8.5.2.1, Figure 8.27 Control Node Activations, add the following class as a subclass of ControlNodeActivation:
FlowFinalNodeActivation
+ fire ( incomingTokens: Token [*] )
After Subclause 8.5.2.2.9 DecisionNodeActivation, add the following subclause (and renumber subsequent subclauses appropriately).
8.5.2.2.10 FlowFinalNodeActivation
A flow final node activation is a control node activation for a node that is a flow final node.
Generalizations
• “ControlNodeActivation” on page 202
Attributes
None
Associations
None
Operations
[1] fire ( in incomingTokens : Token [0..*] )
// Consume all incoming tokens.
Debug.println("[fire] Flow final node " + this.node.name + "...");
for (int i = 0; i < incomingTokens.size(); i++) {
Token token = incomingTokens.getValue(i);
token.withdraw();
}
Actions taken:
October 6, 2009: received issue
January 7, 2013: closed issue
Discussion: The FTF agrees that this is a problem that needs fixing but, due to lack of time, decided to defer its resolution to a future RTF working on this specification.
Revised Text:
None.
Disposition: Deferred
Issue 15130: An action may not stop firing again (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: The code for ActionActivation::fire, as updated for the resolution of Issue 15094, is missing the statement “fireAgain := false;” that should appear after “_beginIsolation();” and before “_endIsolation();”. As a result, if an action fires again at least once, but eventually is not ready to fire any longer, fireAgain will still stay true, causing it to erroneously continue to fire anyway.
Resolution: agreed
Revised Text: In Subclause 8.6.2.2.1, in ActionActivation::fire, after “_beginIsolation();”, add the statement:
fireAgain := false;
Actions taken:
March 21, 2010: received issue
January 7, 2013: closed issue
Issue 15986: fUML 1.1 should be based on UML 2.4 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models, FTF Beta 3 (ptc/10-03-14)
Foundational UML (fUML) 1.0 as finalized is based on UML 2.3. With the completion of the UML 2.4 RTF, fUML should be moved to UML 2.4. This would be consistent with the recently adopted Alf action language specification, which will be finalized based on UML 2.4.
Fortunately, nothing seems to have changed in UML 2.4 that would substantively effect the specification of the fUML abstract syntax subset. However, the fUML normative XMI should be regenerated consistent with UML 2.4/XMI 2.4. Further, UML 2.4 has separated the primitive type model into a separate XMI file with normative XMI IDs, and these should be used for referencing those types in the normative XMI for the fUML Foundational Model Library.
Resolution: The following issues resolved in UML 2.4 and UML 2.4.1 have an impact on the fUML subset.
• Issue 10831: “PackageableElement::visibility” uses “false” as default value
• Issue 12583: OCL 2.0 8.2 Real
• Issue 13718: Section 12.3.48 on page 412
• Issue 13993: UML 2.2 Issue - availability of PrimitiveTypes for UML models
• Issue 14631: All enumeration literals in the model have their "classifier" collections empty
• Issue 14632: Associations with same name that live in different packages violate unique name constraint
• Issue 14926: is composite, but does not subset ownedElement
• Issue 14931: remove BehavioredClassifier::ownedTrigger
• Issue 14977: Matching subsettting across association ends
• Issue 15369: UML 2.4: Add Property::isId
• Issue 15370: UML 2.4: Add Package::URI
• Issue 15526: Missing subsetting of redefinitionContext by Property::owningAssociation
• Issue 15664: Property::isID should not be optional
• Issue 16232: No unambiguous way in UML 2.4 to serialize StructuredActivityNode
Further, comparison if the fUML 1.0 abstract syntax model with that of UML 2.4.1 identifies the following additional corrections need to fUML.
• Remove Class::isAbstract attribute (this is already inherited from Classifier).
• Add default of true for Generalization::isSubstitutable.
• Note exclusion of Parameter::defaultValue, Parameter::default and Property::default.
• Add default of “in” for Parameter::direction.
See also the resolution to Issue 15987 “The fUML Foundational Model Library should support the new UML 2.4 Real primitive type”. For simplicity, all revisions related to the new Real type are handled in that resolution.
Revised Text: Clause 3 Normative References
Replace the content of the clause with:
The following normative documents contain provisions that, through reference in this text, constitute provisions of this specification.
The following OMG standards provided the source for the foundational subset.
• UML 2.4.1 Infrastructure Specification (formal/11-08-05)
• UML 2.4.1 Superstructure Specification (formal/11-08-06)
• MOF 2.4.1 Core Specification (formal/11-08-07)
• OCL 2.0 Specification (formal/06-05-01)
XML Metadata Interchange (XMI) provides a syntactic interchange mechanism for models. It is expected that models conforming to this specification will be interchanged using XMI.
• MOF 2.4.1 XMI Mapping Specification (formal/11-08-09)?
Subclause 7.2 Classes
In Subclause 7.2.2.1 Overview, after the existing bullet under “From Features (see Figure 7.9)”, add:
• Parameter::defaultValue. Implicitly computing a default value for a behavioral feature (or behavior) would require coordination of multiple UML actions, since call actions always require explicit inputs or outputs to be provided.
• Parameter::default. This is excluded because default values for parameters are not included in fUML.
After the first bullet under “From Classes (see Figure 7.11)”, add:
• Property::default. This is excluded because default values for properties are not included in fUML.
In Figure 7.5 Namespaces, in the symbol for PackageableElement shown immediately, under NamedElement, add the attribute
• + visibility : VisibilityKind = public {redefines visibility}
In Figure 7.8 Classifiers,
• In the specification for the attribute Generalization::isSubstitutable, add “ = true”.
• In the annotations to the association end attribute, add “subsets redefinableFeature, subsets feature”.
• Add the annotation “{subsets redefinitionContext, subsets featuringClassifier}” to the association end classifier opposite to attribute.
• Add the annotation “{subsets memberNamespace}” to the association end classifier opposite to inheritedMember.
• Add the annotation “{readOnly, union}” to the association end redefinedElement.
In Figure 7.9 Features,
• In the specification for the attribute Parameter::direction, add “ = in”.
• In the annotation for the association end feature add the annotations “union, subsets member}”.
• In the annotations for the association end featuringClassifier add “subsets memberNamespace”.
In Figure 7.10 Operations,
• Add the annotation “{subsets redefinedElement}” to the association end redefinedOperation.
• Add the annotation “{subsets redefinableElement}” to the association end operation opposite redefinedOperation.
• Replace the annotation “{subsets namespace}” on the association end operation opposite to ownedParameter with “{subsets ownerFormalParam}”.
• Add the annotation “{readOnly} to the association end “type”.
In Figure 7.11 Classes,
• Remove the attribute isAbstract from class Class.
• In class Property, add the attribute
o + isId : Boolean = false
• Add the annotation “{redefines general}” to the association end superclass.
• Add the annotation “{subsets classifier}” to the association end class opposite to superclass.
• In the annotation for the association end ownedOperation, add the annotation “subsets redefinableElement”.
• In the annotation for the association end class opposite to ownedOperation, add the annotation “subsets redefinitionContext”.
• In the annotation for the association end class opposite to ownedAttribute, remove the annotation “subsets featuringClassifier”.
• In the annotation for the association end memberEnd, replace “subsets ownedMember” with “subsets member”.
• Add the annotation “{subsets memberNamespace}” to the association end association opposite to memberEnd.
• Add the annotation “{subsets owningAssociation}” to the association end association opposite to navigableOwnedEnd.
In Figure 7.12 Data Types,
• In the annotation for association end datatype opposite to ownedAttribute, remove “subsets featuringClassifier”.
• Add a unidirectional association from EnumerationLiteral to Enumeration with association ends:
o enumerationLiteral * {redefines instanceSpecificiation}
o /classifier 1 {redefines classifier}
In Figure 7.13 Packages,
• In class Package, add the attribute
o + URI : String [0..1] {id}
• Replace the annotation “{subsets namespace}” for the association end package with “{subsets owningPackage}”.
• Replace the annotation “{subsets namespace}” for the association end nestingPackage with “{subsets owningPackage}”.
In Subclause 7.2.2.3 Class, under “Attributes”,
• Remove “isAbstract : Boolean = false”
In Subclause 7.2.2.10 EnumerationLiteral, under “Attributes”
• Before the existing bullet, add a bullet for “classifier : Enumeration”.
• Change “enumeration : Enumeration [0..1]” to “enumeration : Enumeration”
In Subclause 7.2.2.12 Generalization, under “Attributes”,
• At the end of the bullet for “isSubstitutable", add “ = true”
In Subclause 7.2.2.2.25 Package, under “Attributes”, replace “None” with
• URI : String [0..1] {id}
In Subclause 7.2.2.2.26 PackageableElement, under “Attributes”, replace “None” with
• visibility : VisibilityKind = public
In Subclause 7.2.2.2.28 Parameter, under “Attributes”,
• At the end of the bullet for “direction”, add “ = in”.
In Subclause 7.2.2.2.30 Property, under “Attributes”, after the bullet for “isDerivedUnion”, add:
• isId : Boolean = false
Subclause 7.3 Common Behaviors
In Subclause 7.3.1 Overview, remove “From Triggers (see Figure 7.17)” and the following bullet.
In Figure 7.15 Common Behavior,
• Add the annotation “{subsets namespace}” to the association end behavioredClassifier opposite to ownedBehavior.
• Add the annotation “{redefines behavioredClassifier}” to the association end behavioredClassifier opposite to classifierBehavior.
• Add the annotation “{readOnly}” to the association end context.
• Add the annotation “{subsets namespace}” to the association end behavior opposite to ownedParameter.
In Figure 7.16 Reception,
• Add the annotation “{subsets memberNamespace, subsets featuringClassifier}” to the association end ownedReception.
Subclause 7.4 Activities
In Figure 7.23 Flows,
• Add the annotation “{subsets owner}” to the association end activityEdge.
In Figure 7.24 StructuredNodes,
• Add a symbol for the class Activity.
• Add an association from Activity to StructuredActivityNode with the ends
o +activity 0..1 {redefines activity}
o +structuredActivityNode * {readOnly, subsets node}
• Add the annotation “{subsets owner}” to the two inStructuredNode association ends and the conditionalNode association end opposite to clause.
• Add the annotation “{subsets ownedElement}” to the association ends node, edge and clause.
• Add the annotation “{subsets action}” to the two structuredActivityNode association ends.
• Add the annotation “{subsets structuredActivityNode}” to the conditionalNode association end opposite to result and the two loopNode association ends opposite to loopVariableInput and result.
Subclause 7.5 Actions
In Figure 7.28 Basic Pins,
• Add the annotation “{subsets owner}” to the two action association ends.
In Figure 7.29 Basic Invocation Actions,
• Add the annotation “{subsets action}” to the end of every composition association whose opposite end is an InputPin or OutputPin.
In Figure 7.30 Object Actions,
• Add the annotation “{subsets action}” to the end of every composition association whose opposite end is an InputPin or OutputPin.
• Add the annotation “{subsets ownedElement}” to the value association end.
• Add the annotation “{subsets owner}” to the valueSpecificationAction association end opposite to value.
In Figure 7.31 Structural Feature Actions,
• Add the annotation “{subsets action}” to the end of every composition association whose opposite end is an InputPin or OutputPin.
In Figure 7.32 Link Identification,
• Add the annotation “{subsets action}” to the linkAction association end opposite to inputValue.
• Add the annotation “{subsets ownedElement}” to the endData association end.
• Add the annotation “{subsets owner}” to the linkAction association end opposite to endData.
In Figure 7.33 Read Link Action,
• Add the annotation “{subsets action}” to the readlinkAction association end.
In Figure 7.34 Write Link Actions,
• Add the annotation “{subsets action}” to the clearAssociationAction association end.
• Add the annotation “{redefines linkAction}” to the createLinkAction and destroyLinkAction association ends.
In Figure 7.35 Accept Event Actions,
• Add the annotation “{subsets ownedElement}” to the trigger association end.
• Add the annotation “{subsets owner}” to the acceptEventAction association end opposite to trigger.
• Add the annotation “{subsets action}” to the acceptEventAction association end opposite to result.
In Figure 7.36 Object Lifecycle Actions,
• Add the annotation “{subsets action}” to the end of every composition association whose opposite end is an InputPin or OutputPin.
Clause 9 Foundational Model Library
In Figure 9.1, replace the package UML::AuxiliaryConstructs::PrimitiveTypes package with PrimitiveTypes.
In Subclause 9.1, first paragraph,
• In the first sentence, replace “…AuxiliaryConstructs::PrimitiveTypes package from the UML 2 metamodel (see sub clause 17.4 of the UML 2 Superstructure Specification).” with “…PrimitiveTypes package from the UML 2 infrastructure (see sub clause 13.1 of the UML 2.4.1 Infrastructure Specification).”
• In the last sentence, replace “AuxiliaryConstructs::PrimitiveTypes” with “PrimitiveTypes”.
fUML_Syntax.xmi
In the normative XMI, change the names of the following associations:
• IntermediateActivities::A_outgoing_source to A_outgoing_source_node
• IntermediateActivities::A_incoming_target to A_incoming_target_node
Actions taken:
January 26, 2011: received issue
January 7, 2013: closed issue
Discussion:
Issue 15987: The fUML Foundational Model Library should support the new UML 2.4 Real primitive type (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models, FTF Beta 3 (ptc/10-03-14)
UML 2.4 has introduced a new Real primitive type. This should be supported by a new package of primitive functions in the fUML Foundational Model Library.
Resolution: The UML 2.4.1 Infrastructure specification states that “A real is a primitive type representing the mathematical concept of real” and that “An instance of Real is an element in the infinite set of real numbers.” However, some care needs to be taken in defining the fUML execution semantics of the Real type and supporting primitive functions, so that it is possible for a real implementation to conform to those semantics.
The UML specification also says that “An instance of Integer is an element in the (infinite) set of integers…”. And the base semantics for buml:Integer in Subclause 10.3.1.2 of the fUML 1.0 specification does, indeed, include the mathematical axioms necessary to define this infinite set. However, Subclause 9.1 includes the permission that “…a conforming implementation may limit the supported values [of Integer] to a finite set.”
Similarly, fUML should allow conforming implementations to limit the supported values of Real to a finite set. However, for Real numbers, this means more than just limiting the upper and lower bounds of the supported range of Real numbers. It also means dealing with the fact that Real numbers can only be represented to finite precision in an actual implementation.
Generally, programming languages provide floating-point representations that approximate Real numbers. However, this is an implementation representation, and the most commonly used standard reference on floating-point numbers, IEEE 754, is a standard for the implementation of floating-point computation.
For fUML, it is necessary to provide a precise semantic specification for Real numbers that is implementation independent but that provides clear criteria for the conformance of actual implementations. This should allow implementations based on a floating-point standard such as IEEE 754 but also allow implementations using, e.g., fixed-point computation or exact rational number computation.
This can be achieved in three steps.
1. Axioms for the Real type need to be added to the fUML base semantics in Clause 10.
2. Criteria are needed in Clause 9 for conformance to the Real type as it is to be provided in the fUML Foundational Model Library. The set of Real numbers includes values that cannot be represented in finite precision (e.g., irrational numbers and those rational numbers with infinite repeating digit representations in the base being used). So, some permission is needed to allow for the conformance of implementations using, e.g., finite-precision floating-point representations. In addition, IEEE 754 requires some additional special values be represented in the floating-point formats it defines. Since it is expected that it will be common that the fUML Real type will be implemented using a floating-point representation based on IEEE 754, it is necessary to allow for the inclusion of such values in an implementation of Real.
3. Criteria are needed in Clause 9 for conformance to the semantics of the primitive functions for Real to be provided in the Foundational Model Library. The specification of the primitive functions for Real in the Foundational Model Library will define the exact real number result of applying those functions. It is then necessary to define how these exact results may be represented in a conforming implementation that takes advantage of some or all of the permissions allowed relative to the representation of Real numbers.
This resolution also presumes the resolution of Issue 15986, “fUML 1.1 should be based on UML 2.4”. For simplicity, all revisions related to the new Real type have been included here. This includes changes to Clause 7 Abstract Syntax, Clause 8 Execution Model and Annex A Java to UML Activity Mapping, as well as the changes to Clauses 9 and 10 discussed above.
Revised Text: Revised Text:
Clause 7 Abstract Syntax
In Figure 7.6 Expressions, add LiteralReal as a subclass of LiteralSpecification, with one attribute:
• + value : Real
After Subclause 7.2.2.17 LiteralNull, add the following subclause:
LiteralReal
Generalizations
• “LiteralSpecification” on page xx
Attributes
• value : Real
Associations
None
Additional Constraints
None
Clause 8 Execution Model
In Subclause 8.2.2.2, under “Primitive Behaviors and Primitive Types”, in the last sentence of the last paragraph, change “…Boolean, Integer, String, and UnlimitedNatural…” to “…Boolean, Integer, Real, String, and UnlimitedNatural…”.
In Figure 8.11, add the following class as a subclass of PrimitiveValue:
RealValue
+ value : Real
+ specify ( ) : ValueSpecification
+ equals ( otherValue : Value ) : Boolean
+ copy ( ) : Value
# new_ ( ) : Value
+ toString ( ) : String
In Figure 8.13, add the following class as a subclass of LiteralEvaluation:
LiteralRealEvaluation
+ evaluate ( ) : Value [0..1]
After Subclause 8.3.2.2.15, add the subclause
LiteralRealEvaluation
A literal real evaluation is an evaluation whose specification is a literal real.
Generalizations
• “LiteralEvaluation” on page 138
Attributes
None
Associations
None
Operations
[1] evaluate ( ) : Value [0..1]
// Evaluate a real integer, producing a real value.
LiteralReal literal = (LiteralReal)specification;
RealValue realValue = new RealValue();
realValue.type = this.getType("Real");
realValue.value = literal.value;
return realValue;
After Subclause 8.3.2.2.19, add the subclause
RealValue
A real value is a primitive value whose type is Real.
Generalizations
• “PrimitiveValue” on page 143
Attributes
• value : Real?
The actual Real value.
Associations
None
Operations
[1] copy ( ) : Value
// Create a new real value with the same value as this real value.
RealValue newValue = (RealValue)(super.copy());
newValue.value = this.value;
return newValue;
[2] equals ( in otherValue : Value ) : Boolean
// Test if this real value is equal to the otherValue.?
// To be equal, the otherValue must have the same value as this real value.
boolean isEqual = false;
if (otherValue instanceof RealValue) {?
isEqual = ((RealValue)otherValue).value == this.value;
}
return isEqual;
[3] new_ ( ) : Value
// Create a new real value with no value.
return new RealValue();
[4] specify ( ) : ValueSpecification
// Return a literal real with the value of this real value.
LiteralReal literal = new LiteralReal();
literal.type = this.type;
literal.value = this.value;
return literal;?
[5] toString ( ) : String
String stringValue = "";
if (this.value == 0) {
stringValue = "0";
} else {?
float positiveValue = this.value;
if (positiveValue < 0) {
positiveValue = -positiveValue;
}
int exponent = 0;
if (postiveValue < .1) {
while (positiveValue < .1) {
positiveValue = positiveValue * 10;
exponent = exponent - 1;
}
else if (positiveValue > 1) {
while (positiveValue > 1) {
positiveValue = positiveValue / 10;
exponent = exponent + 1;
}
}
// This gives 10 significant digits in the mantissa.
for (int i=0; i<10; i++) {
positiveValue = positiveValue * 10;
}
IntegerValue integerValue = new IntegerValue();
integerValue.value = (int)positiveValue;
stringValue = “0.” + integerValue.toString();
integerValue.value = exponent;
stringValue = stringValue + “E” + integerValue.toString;
if (this.value < 0) {?
stringValue = "-" + stringValue;
}
}
return stringValue;
Clause 9 Foundational Model Library
In Subclause 9.1 Primitive Types, Table 9.1, add the following row after the row for Integer:
Real The Real type has literal values in the infinite, continuous set of real numbers. However, a conforming implementation may limit the support values to a finite subset (see 9.2.3 for further discussion of this).
In Subclause 9.2 Primitive Behaviors, add a RealFunctions package to Figure 9.2.
In the first paragraph of Subclause 9.2.2 Integer Functions, remove the sentence:
The OCL “/” operation is not included, since this returns a Real value, and the Foundational Model Library does not support a Real primitive type.
In Table 9.3, add the following row, after the row for the “*” function:
/(x: Integer, y: Integer): Real[0..1] The value of the division of x by y.
Pre: y<>0
Post: result = ToReal(x) / ToReal(y)
NOTE: The ToReal and “/” functions used here are those from the RealFunctions package (see 9.2.3).
Add the following subclause and renumber subsequent subclauses and tables appropriately:
9.2.3 Real Functions
Table 9.4 lists the function behaviors that are included in the package RealFunctions. The naming is consistent with OCL, including the use of the conventional symbols for arithmetic functions, except that the negation function is named “Neg”, rather than overloading the symbol “-”, and alphabetic names are capitalized, per the usual convention for behaviors (as kinds of classes). The Foundation Model Library also provides ToString and ToInteger functions not found in OCL 2.0. The ToReal function does correspond to an OCL operation, though, in OCL, it is a String operation.
Table 9.4 – Foundation Model Library Real Functions
Function Signature Description
Neg(x: Real): Real The negative value of x.
+(x: Real, y: Real): Real The value of the addition of x and y.
-(x: Real, y: Real): Real The value of the subtraction of x and y.
Post: result + y = x
Inv(x: Real): Real The inverse (reciprocal) value of x.
*(x: Real, y: Real): Real The value of the multiplication of x and y.
/(x: Real, y: Real): Real[0..1] The value of the division of x by y.
Pre: y<>0
Post: result * y = x
Abs(x: Real): Real The absolute value of x.
Post: if x < 0 then result = Neg(x) else result = x endif
Floor(x: Real): Integer The largest integer that is less than or equal to x.
Post: result <= x And result + 1 > x
Round(x: Real): Integer The integer that is closest to x. When there are two such integers, the largest one.
Post: (Abs(x - result) < 0.5) Or ((Abs(x - result) = 0.5) And result > x)
Max(x: Real, y: Real): Real The maximum of x and y.
Post: if x >= y then result = x else result = y endif
Min(x: Real, y: Real): Real The minimum of x and y.
Post: if x <= y then result = x else result = y endif
<(x: Real, y: Real): Boolean True if x is less than y.
>(x: Real, y: Real): Boolean True if x is greater than y.
Post: result = Not(x <= y)
<=(x: Real, y: Real): Boolean True if x is less than or equal to y.
Post: result = (x = y) Or (x < y)
>=(x: Real, y: Real): Boolean True if x is greater than or equal to y.
Post: result = (x = y) Or (x > y)
ToString(x: Real): String Converts x to a String value.
Post: ToReal(result) = x
ToInteger(x: Real): Integer Converts x to an Integer value, truncating towards zero.
Post: if x >= 0 then Floor(x) else Neg(Floor(Neg(x)) endif
ToReal(x: String): Real[0..1] Converts x to a Real value.
Pre: x has the form of a legal Real value.
The set of Real numbers includes values that cannot be represented in finite precision (e.g., irrational numbers and those rational numbers with infinite repeating digit representations in the base being used). Therefore, implementations are given the following permissions for representing Real numbers and performing computations on them, while still conforming to this specification.
NOTE: The permissions below are intended, in particular, to allow the conformance of implementations using finite-precision floating-point representations for Real numbers (such as those based on the popular IEEE 754 standard), while still allowing for other implementations that may not need to take advantage of all the allowed permissions.
1. A conforming implementation may support only a limited range of Real values, such that the absolute value of any supported value is less than or equal to a specified maximum value. If the implementation limits the range of values support for Integer, then the maximum value specified for Real must be no less than the greatest absolute value of any supported Integer value.
2. A conforming implementation may support only a restricted value set for Real, defined as a non-dense subset of the infinite set of rational numbers (such that any bounded interval of this value set contains only a finite set of values) including zero and with no upper or lower bound. If the implementation limits the range of values supported for Integer, then the smallest positive value in the restricted value set shall be at least as small as the reciprocal of the largest supported Integer value.
3. A conforming implementation may provide distinct representations for Real positive zero and Real negative zero. These values shall be considered equal for the purposes of all comparison functions. However, they may be distinguished in certain arithmetic computations (see below).
4. A conforming implementation may include additional special values that are instances of the Real type but are not numeric values (such as infinite values and “not a number” values). Note that, even if included in an implementation of the Real type, none of these special values have any standard literal representation in UML.
The functions in the RealFunctions package are specified in Table 9.4 in terms of the semantics for mathematical Real numbers, as defined in Subclause 10.3.1. However, an implementation that takes advantage of some or all of the above permissions may not be able to produce exact results for some computations using these functions. Therefore, conformance to the function behaviors given in Table 9.4 shall be interpreted as follows.
• Since a restricted value set is non-dense and unbounded, any exact value that is not in such a set will be between two values that are in the set. If a conforming implementation supports only a restricted value set, and the result of a computation is not a member of this set, then the implementation may implement the computation as resulting in one of the two values in the restricted value set that the exact result is between. (If the exact value of the computation is non-zero, but the chosen value in the restricted value set is zero, then the computation is said to underflow.)
• If a conforming implementation supports only a limited range of values, then a computation that results in an exact value that is outside that range is said to overflow. The implementation may implement an overflowing computation as resulting in a special value (e.g., positive or negative infinity). If not, an overflowing computation shall be implemented as having an empty result.
• If a numeric result is not defined for a call to a primitive function resulting in a Real value, because one of the arguments is a special value or because a precondition is violated, then a conforming implementation may produce a special value for its result. Otherwise, the computation shall be implemented as having an empty result.
• If a conforming implementation supports signed zero, then multiplication of a numeric value by positive zero shall result in positive zero, while multiplication of a numeric value by negative zero shall result in negative zero. A conforming implementation shall not otherwise distinguish between positive and negative zero in any call to a primitive function that is specified as resulting in a numeric result. However, it may distinguish between them if the result is implemented as a special value (e.g., division by negative zero may result in negative infinity).
• Other than as given above, this specification does not define the result of calling a primitive function in which one or more of the arguments is a special value.
Clause 10 Base Semantics
Replace the contents of Subclause 10.3.1.2 Numbers with
The less-than relation.
(forall (x y)
(if (buml:less-than x y)
(and (buml:Real x)
(buml:Real y))))
(forall (x y)
(if (buml:less-than x y)
(and (not (buml:less-than y x))
(not (= x y)))))
(forall (x y)
(if (and (buml:Real x)
(buml:Real y))
(or (form:less-than x y)
(form:less-than y x)
(= y x))))
(forall (x y)
(iff (buml:less-than x y)
(and (buml:Real x)
(buml:Real y)
(not (buml:less-than y x))
(not (= x y)))))
(forall (x y z)
(if (and (buml:less-than x y)
(buml:less-than y z))
(buml:less-than x z)))
(forall (x z)
(if (buml:less-than x z)
(exists (y)
(and (buml:less-than x y)
(buml:less-than y z)))))
The add relation.
(forall (x y z)
(if (buml:add x y z)
(and (buml:Real x)
(buml:Real y)
(buml:Real z))))
(forall (x y)
(if (and (buml:Real x)
(buml:Real y))
(exists (z)
(buml:add x y z))))
(forall (x y z1 z2)
(if (and (buml:add x y z1)
(buml:add x y z2))
(= z1 z2)))
(forall (x y zxy zyx)
(if (and (buml:add x y zxy)
(buml:add y x zyx))
(= zxy zyx)))
(forall (x y z xy yz rxy ryz)
(if (and (buml:add x y xy)
(buml:add xy z rxy)
(buml:add y z yz)
(buml:add x yz ryz))
(= rxy ryz)))
(forall (x y xz yz)
(if (and (buml:add x z xz)
(buml:add y z yz)
(buml:less-than x y))
(buml:less-than xz yz)))
(buml:Real form:0)
(forall (x x0)
(if (buml:add x form:0 x0)
(= x x0)))
(forall (x y)
(iff (buml:neg x y)
(buml:add x y form:0)))
(forall (x)
(if (buml:Real x)
(exists (nx)
(buml:neg x nx))))
The mult relation.
(forall (x y z)
(if (buml:mult x y z)
(and (buml:Real x)
(buml:Real y)
(buml:Real z))))
(forall (x y)
(if (and (buml:Real x)
(buml:Real y))
(exists (z)
(buml:mult x y z))))
(forall (x y z1 z2)
(if (and (buml:mult x y z1)
(buml:mult x y z2))
(= z1 z2)))
(forall (x y zxy zyx)
(if (and (buml:mult x y zxy)
(buml:mult y x zyx))
(= zxy zyx)))
(forall (x y z xy yz rxy ryz)
(if (and (buml:mult x y xy)
(buml:mult xy z rxy)
(buml:mult y z yz)
(buml:mult x yz ryz))
(= rxy ryz)))
(forall (x y xy)
(if (and (buml:mult x y xy)
(buml:less-than form:0 x)
(buml:less-than form:0 y))
(buml:less-than form:0 xy)))
(buml:Real form:1)
(forall (x x1)
(if (buml:mult x form:1 x1)
(= x x1)))
(forall (x y)
(iff (buml:inv x y)
(buml:mult x y form:1)))
(forall (x)
(if (and (buml:Real x)
(not (= x form:0)))
(exists (ix)
(buml:inv x ix))))
(forall (x y z yz rxyz xy xz xyxz)
(if (and (add y z yz)
(mult x yz xyz)
(mult x y xy)
(mult x z xz)
(add xy xz xyxz))
(= xyz xyxz)))
(less-than form:0 form:1)
Rational, integer, natural, unlimited natural, and whole numbers.
(forall (x)
(if (form:RationalNumber x)
(buml:Real x)))
(forall (x z)
(if (and (form:Rational x)
(form:Rational z)
(buml:less-than x z))
(exists (y)
(and (form:Rational y)
(buml:less-than x y)
(buml:less-than y z)))))
(forall (x z)
(if (and (form:Rational x)
(form:Rational z)
(buml:less-than x z))
(exists (y)
(and (buml:Real y)
(not (form:Rational y))
(buml:less-than x y)
(buml:less-than y z)))))
(forall (y)
(if (and (buml:Real y)
(not (form:Rational y)))
(and (not (exists (xu)
(and (form:Rational xu)
(forall (x)
(and (Rational x)
(buml:less-than x y)
(or (buml:less-than x xu)
(= x xu)))))))
(not (exists (zl)
(and (form:Rational zl)
(forall (z)
(and (Rational z)
(buml:less-than y z)
(or (buml:less-than zl z)
(= zl z))))))))))
(forall (x)
(if (buml:Integer x)
(form:Rational x)))
(forall (x y)
(iff (form:add-one x y)
(form:add x form:1 y)))
(forall (x)
(iff (buml:Integer x)
(or (= x form:0)
(exists (y)
(and (buml:Integer y)
(or (form:add-one y x)
(form:add-one x y)))))))
(forall (x)
(iff (form:NaturalNumber x)
(and (buml:Integer x)
(or (= x form:0)
(buml:less-than form:0 x)))))
(forall (x)
(iff (buml:UnlimitedNatural x)
(or (form:NaturalNumber x)
(= x buml:*))))
(forall (x)
(iff (form:WholeNumber x)
(and (form:NaturalNumber x)
(not (= x form:0)))))
Annex A Java to UML Activity Mapping
In Table A.1, after the row for type “int”, add the following row:
float Real
Change the title of Subclause A.4.13 from “Type Cast” to “Type Cast (non-primitive)”.
After Subclause A.4.13, add the following subclause:
A.4.14 Type Cast (Numeric)
Java
(<type>)<expression>
• The type must be int or float.
• The expression being cast must be of type int or float.
UML
• A type cast from int to int, float to float or int to float is mapped as the expression being cast. The cast itself is ignored, other than that the result pin for the expression being mapped is always given the UML type corresponding to the type of the cast.
• A type cast from float to int maps to a call behavior action for the ToInteger behavior. The result output pin becomes the result pin for the mapping. The argument input pin of the call behavior action is connected by an object flow to the result pin of the mapping of the expression being cast.
Note
• In the base semantics, an integers is a kind of real number (see 10.3.1.2), so no actual operation is needed to cast an integer to a real.
Actions taken:
January 26, 2011: received issue
January 7, 2013: closed issue
Discussion:
Issue 16654: Error in ExpansionRegionActivation::takeOfferedTokens (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundation Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-01)
Subclause: 8.5.4.2.3 ExpansionRegionActivation
In the ExpansionRegionActivation class, operation [8] takeOfferedTokens is missing an initial call to super.takeOfferedTokens(). This means that, when an expansion region activation fires, it does not properly handle tokens on control flows incoming to the expansion region, nor does it fire any input pin activations for the region, both of which should be handled as usual for an action. Because of this, the subsequent copying of input tokens from input pin activations in ExpansionRegionActivation never actually produces any tokens, even though some may have been offered to the input pins.
Resolution: agreed
Revised Text: In Subclause 8.5.4.2.3, in ExpansionRegionActivation::takeOfferedTokens, at the beginning, add the statement:
super.takeOfferedTokens();
Actions taken:
November 7, 2011: received issue
January 7, 2013: closed issue
Issue 16686: Error in CreateLinkAction semantics (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.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.6.3.x CreateLinkActionActivation
In Subclause 8.6.3.1 (Overview), under “Link Actions”, it says for a Create Link Action that “if a link already exists in the association extent with the same tuple of values, and all the ends of the association are specified as unique, then no new link is actually created (though this is not an error).” However, the specification for CreateLinkActionActivation::doAction in Subclause 8.6.3.2.4 always creates a new link even if an identical link already exists (unless isReplaceAll=true for one of the ends), regardless of whether the ends of the association are all unique.
Resolution: Agreed. Actually it is OK to always create a new link, as long as a link with all matching ends is destroyed first in the case of an association with all ends unique, since links with matching ends are not distinguishable
Revised Text: In Subclause 8.6.3.4, in doAction, add the following to the initial comment block, before the first sentence:
// If the association has any unique ends, then destroy an existing link
// that matches all ends of the link being created.
Replace the statement “Link oldLink = null;” and the following for loop with:
boolean unique = false;
for (int i = 0; i < endDataList.size(); i++) {
if (endDataList.getValue(i).end.multiplicityElement.isUnique) {
unique = true;
}
}
for (int i = 0; i < extent.size(); i++) {
ExtensionalValue value = extent.getValue(i);
Link link = (Link) value;
boolean match = true;
boolean destroy = false;
int j = 1;
while (j <= endDataList.size()) {
LinkEndCreationData endData = endDataList.getValue(j - 1);
if (this.endMatchesEndData(link, endData)) {
if (endData.isReplaceAll) {
destroy = true;
}
} else {
match = false;
}
j = j + 1;
}
if (destroy | unique & match ) {
link.destroy();
}
}
In the subsequent for loop, remove the following if statement:
if (oldLink != null) {
if (oldLink.getFeatureValue(endData.end).position < insertAt) {
insertAt = insertAt - 1;
}
}
Actions taken:
November 14, 2011: received issue
January 7, 2013: closed issue
Issue 16687: Duplicate code for ActionActivation::putToken (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.6.2.2.1 ActionActivation
The code listed under operation [12] PutToken for class ActionActivation is accidentally duplicated. The lines starting with the second set of comments to the end should be deleted.
Resolution: agreed
Revised Text: In Subclause 8.6.2.2.1 remove the repeated code for PutToken, from the second set of comments to the end.
Actions taken:
November 15, 2011: received issue
January 7, 2013: closed issue
Issue 16948: Error in DecisionNodeActivation semantics (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: : Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-01)
Subclause: 8.5.2.2.9 DecisionNodeActivation
In the method for the DecisionNodeActivation::getDecisionInputFlowValue operation contains the statement:
value = ((ObjectToken)(tokens.getValue(0))).value;
Since a decision input flow must be an object flow, it would seem reasonable to be able to assume that this flow would only contain ObjectTokens. However, all tokens offered by ForkNodeActivations are wrapped in ForkTokens, which is directly a subclass of Token. If such a token is offered on a decision input flow, then the above cast will fail.
To fix this, the above statement should be replaced with:
value = tokens.getValue(0).getValue();
The getValue operation is defined for all types of tokens (it returns null for control tokens, but that would not be an issue here).
Resolution: agreed
Revised Text: In Subclause 8.5.2.2.9, in the getDecisionInputFlowValue operation, replace the statement
value = ((ObjectToken)(tokens.getValue(0))).value;
with
value = tokens.getValue(0).getValue();
Actions taken:
January 9, 2012: received issue
January 7, 2013: closed issue
Issue 17168: Spurious comment on operation PinActivation::fire (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/11-02-01)
Subclause: 8.6.2.2.8 PinActivation
The operation PinActivation::fire includes the comment “[Note that a pin will consume all tokens offered to it, even if this is more than the multiplicity upper bound, but will only offer tokens up to that upper bound.]” However, this is not true in fUML as finalized. The incoming tokens passed to the fire operation are determined using the takeOfferedTokens operation, which is defined to “Take only a number of tokens only up to the limit allowed by the multiplicity upper bound of the pin for this activation.”
Resolution: agreed
Revised Text: In Subclause 8.6.2.2.8, in the fire operation, remove the comment “[Note that a pin will consume all tokens offered to it, even if this is more than the multiplicity upper bound, but will only offer tokens up to that upper bound.]”.
Actions taken:
February 23, 2012: received issue
January 7, 2013: closed issue
Discussion:
Issue 17200: Error in RemoveStructuralFeatureVauleActionActivation::doAction (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0
Subclause: 8.6.3.2.12 RemoveStructuralFeatureValueActionActivation
The following conditional appears toward the end of the specification of the RemoveStructuralFeatureValueActionActivation::doAction() operation:
if (featureValue.values.size() <= removeAt) {
featureValue.values.remove(removeAt - 1);
}
The “<=” operator in the condition should instead be “>=”.
Resolution: agreed
Revised Text: In Subclause 8.6.3.2.12, in doAction operation, in the condition “featureValue.values.size() <= removeAt”, replace “<=” with “>=”.
Actions taken:
February 25, 2012: received issue
January 7, 2013: closed issue
Issue 17201: Bug in DestroyObjectActivation::objectIsComposite (fuml-rtf)
Click here for this issue's archive.
Nature: Clarification
Severity: Significant
Summary: Destroying an object (with "isDestroyLinks" = true) can potentially result in an infinite loop, since the loop variable "i" is never incremented.
Solution:
while (!isComposite & i <= linkFeatureValues.size()) {
FeatureValue featureValue = linkFeatureValues.getValue(i-1);
if (!featureValue.values.getValue(0).equals(reference) &
((Property)featureValue.feature).aggregation == AggregationKind.composite) {
isComposite = true;
}
i = i + 1;
}
Resolution: agreed
Revised Text: In Subclause 8.6.3.2.7 DestroyObjectActionActivation, in the objectIsComposite operation, add “i = i + 1;” at the end of the while loop
Actions taken:
February 28, 2012: received issue
January 7, 2013: closed issue
Issue 17203: Bug in ForkedToken::withdraw when the baseToken is a ForkedToken (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.2.2.10 ForkedToken
ForkedToken::withdraw calls isWithdrawn() to check if its baseToken is withdrawn, and then withdraws it if that is false. The intent is that baseToken.withdraw() only be called once. However, if the baseToken is itself a ForkedToken, then calling withdraw() may only decrement the remainingOffersCount of that token, with isWithdrawn() only becoming true if this count goes to zero. This means that additional calls to withdraw() on the first ForkedToken may result in additional calls to withdraw() on its baseToken, prematurely reducing the remainingOffersCount for the baseToken.
This can be avoided by adding an explicit baseTokenIsWithdrawn flag to ForkedToken that is set when the baseToken is withdrawn and then checked to avoid further withdraws.
Resolution: agreed
Revised Text: In Subclause 8.5.2.2.10, and in Figure 8.27, add the attribute
• baseTokenIsWithdrawn: Boolean.
Indicates whether withdraw() has been called on the base token.
In the withdraw operation, replace:
if (!this.baseToken.isWithdrawn()) {
this.baseToken.withdraw();
}
with:
if (!this.baseTokenIsWithdrawn & !this.baseToken.isWithdrawn()) {
this.baseToken.withdraw();
// NOTE: This keeps a base token that is a forked token from being
// withdrawn more than once, since withdrawing a forked token may
// not actually remove it from its fork node holder.
this.baseTokenIsWithdrawn = true;
}
Actions taken:
February 28, 2012: received issue
January 7, 2013: closed issue
Issue 17205: Error in ActivityNodeActivationGroup::getOutputParameterNodeActivations (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.2.2.5 ActivityNodeActivationGroup
The ActivityNodeActivationGroup::getOutputParameterNodeActivations operation is supposed to return the output ActivityParameterNodeActivations for an Activity. As currently specified, it finds all the ActivityParameterNodes for parameters with direction inout, out and return. However, inout parameters actually have two ActivityParameterNodes: one for input and one for output. The current specification results in the operation incorrectly returning both the input and output nodes for an inout parameter.
The UML well-formedness constraints require that an input ActivityParameterNode only have outgoing edges and that and output ActivityParameterNode only have incoming edges. Therefore, instead of checking the parameter to determine output nodes, getOutputParameterNodeActivations should instead check whether the node activation has incoming edges.
Resolution: agreed
Revised Text: In Subclause 8.5.2.2.5, in the getOutputParameterNodeActivations operation, replace:
ParameterDirectionKind direction = ((ActivityParameterNode) (activation.node)).parameter.direction;
if ((direction.equals(ParameterDirectionKind.inout))
| (direction.equals(ParameterDirectionKind.out))
| (direction.equals(ParameterDirectionKind.return_))) {
with:
if (activation.incomingEdges.size() > 0) {
Actions taken:
February 29, 2012: received issue
January 7, 2013: closed issue
Issue 17209: Error handling creation and destruction of links of associations with ordered ends (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.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:
Issue 17211: ExecutionFactoryL2::instantiateVistor duplicates code from ExecutionFactorL3::instatiateVistor (fuml-rtf)
Click here for this issue's archive.
Source: Commissariat a l Energie Atomique-CEA (Dr. Arnaud Cuccuru, arnaud.cuccuru(at)cea.fr)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.2.3.2.1 ExecutionFactoryL2
The code listed under operation [1] instantiateVisitor for class ExecutionFactoryL2 accidentally duplicates code from ExecutionFactoryL3.instantiateVisitor. The code of ExecutionFactoryL2.instantiateVisitor should be modified to properly cover L2 elements.
Resolution: agreed
Revised Text: In Subclause 8.2.3.2.1, in the instantiateVisitor operation, replace all the code with:
// Instantiate a visitor object for the given element (at Conformance
// Level 2)
SemanticVisitor visitor = null;
if (element instanceof Activity) {
visitor = new ActivityExecution();
}
else if (element instanceof ActivityParameterNode) {
visitor = new ActivityParameterNodeActivation();
}
else if (element instanceof InitialNode) {
visitor = new InitialNodeActivation();
}
else if (element instanceof ActivityFinalNode) {
visitor = new ActivityFinalNodeActivation();
}
else if (element instanceof JoinNode) {
visitor = new JoinNodeActivation();
}
else if (element instanceof MergeNode) {
visitor = new MergeNodeActivation();
}
else if (element instanceof ForkNode) {
visitor = new ForkNodeActivation();
}
else if (element instanceof DecisionNode) {
visitor = new DecisionNodeActivation();
}
else if (element instanceof InputPin) {
visitor = new InputPinActivation();
}
else if (element instanceof OutputPin) {
visitor = new OutputPinActivation();
}
else if (element instanceof CallBehaviorAction) {
visitor = new CallBehaviorActionActivation();
}
else if (element instanceof CallOperationAction) {
visitor = new CallOperationActionActivation();
}
else if (element instanceof SendSignalAction) {
visitor = new SendSignalActionActivation();
}
else if (element instanceof ReadSelfAction) {
visitor = new ReadSelfActionActivation();
}
else if (element instanceof TestIdentityAction) {
visitor = new TestIdentityActionActivation();
}
else if (element instanceof ValueSpecificationAction) {
visitor = new ValueSpecificationActionActivation();
}
else if (element instanceof CreateObjectAction) {
visitor = new CreateObjectActionActivation();
}
else if (element instanceof DestroyObjectAction) {
visitor = new DestroyObjectActionActivation();
}
else if (element instanceof ReadStructuralFeatureAction) {
visitor = new ReadStructuralFeatureActionActivation();
}
else if (element instanceof ClearStructuralFeatureAction) {
visitor = new ClearStructuralFeatureActionActivation();
}
else if (element instanceof AddStructuralFeatureValueAction) {
visitor = new AddStructuralFeatureValueActionActivation();
}
else if (element instanceof RemoveStructuralFeatureValueAction) {
visitor = new RemoveStructuralFeatureValueActionActivation();
}
else if (element instanceof ReadLinkAction) {
visitor = new ReadLinkActionActivation();
}
else if (element instanceof ClearAssociationAction) {
visitor = new ClearAssociationActionActivation();
}
else if (element instanceof CreateLinkAction) {
visitor = new CreateLinkActionActivation();
}
else if (element instanceof DestroyLinkAction) {
visitor = new DestroyLinkActionActivation();
}
else {
visitor = super.instantiateVisitor(element);
}
return visitor;
Actions taken:
March 6, 2012: received issue
January 7, 2013: closed issue
Issue 17213: ActionActivation.sendOffers(): Missing sending of offers on outgoing control flows? (fuml-rtf)
Click here for this issue's archive.
Source: Commissariat a l Energie Atomique-CEA (Dr. Arnaud Cuccuru, arnaud.cuccuru(at)cea.fr)
Nature: Uncategorized Issue
Severity:
Summary: It seems that in ActionActivation.sendOffers(), a loop for sending a control token on outgoing edges is missing. The code should probably be completed with something like:
// *** Send offers on all outgoing edges concurrently. ***
ActivityEdgeInstanceList outgoingEdges = this.outgoingEdges;
for (Iterator i = outgoingEdges.iterator(); i.hasNext();) {
ActivityEdgeInstance outgoingEdge = (ActivityEdgeInstance)i.next();
TokenList tokens = new TokenList();
tokens.addValue(new ControlToken());
outgoingEdge.sendOffer(tokens);
}
Resolution: agreed
Revised Text: In Subclause 8.6.2.2.1 ActionActivation, add the following to the end of operation [15] sendOffers():
// 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);
}
Actions taken:
March 8, 2012: received issue
January 7, 2013: closed issue
Issue 17270: Structural Feature Actions on Data Values Need to Create a new Result Value (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclauses: 8.6.3.2.1 AddStructuralFeatureValueActionActivation, 8.6.3.2.3 ClearStructuralFeatureActionActivation, 8.6.3.2.12 RemoveStructuralFeatureValueAction
Data values are not mutable, so, when given a data value, the structural feature actions are supposed to produce a new data value on the result pin, with the same feature values as for the input data value except for the structural feature on which the action acts. However, the current specifications for the activations of these actions do not copy the value before modifying it, resulting in an incorrect “in place” modification of the feature value of the original data value.
Resolution: Agreed, with the understanding that the term “data value” means specifically an instance of a data type, not an object, which is an instance of a class. Only objects are passed as references, which allows them to be updated mutably. Any value that is not a reference is to be considered an immutable data value.
Revised Text: In Subclauses 8.6.3.2.1, 8.6.3.2.3 and 8.6.3.2.12, in the respective doAction operations, after “} else if (value instanceof StructuredValue) {“, insert:
// If the value is a data value, then it must be copied before
// any change is made.
if (!(value instanceof Reference)) {
value = value.copy();
}
Actions taken:
March 23, 2012: received issue
January 7, 2013: closed issue
Discussion:
Issue 17282: Error in check for enable nodes (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclauses: 8.5.2.2.5 ActivityNodeActivationGroup, 8.5.3.2.4 StructuredActivityNodeActivation
The ActivityNodeActivationGroup::run operation checks which of the node activations in a given set are initially enabled. It does this using the checkIncomingEdges operation to check whether a node has incoming edges with a source within the given set of node activations. The checkIncomingEdges operation in turn uses the ActivityNodeActivation::sourceFor operation to check if an activity node activation is the source for a given activity edge instance. By default, this is true if the activity node activation is the source of the activity edge instance. The sourceFor operation is overridden in ActionActivation to account for the fact that outgoing control flows are attached to an ActionActivation via an anonymous fork node but, otherwise, the default behavior is used.
With the current specification for sourceFor, if a node activation has an incoming edge instance from within a structured activity node activation, rather than from the structured activity node itself, the structured activity node activation will not be considered the source for the edge instance, and the current specification for checkIncomingEdges does not look for sources inside structured activity nodes. This means that, if an activity node only has incoming edges with sources nested within a structured activity node, it may be spuriously considered to be enabled when it really has predecessor dependencies.
Resolution: agreed
Revised Text: In Figure 8.25, add the operation “hasSourceFor(edgeInstance: ActivityEdgeInstance): Boolean” to the class ActivityNodeActivationGroup, and add the following specification for it to Subclause 8.5.2.2.45
hasSourceFor(edgeInstance: ActivityEdgeInstance): Boolean
// Returns true if this activation group has a node activation
// corresponding to the source of the given edge instance.
boolean hasSource = false;
ActivityNodeActivationList activations = this.nodeActivations;
int i = 1;
while (!hasSource & i <= activations.size()) {
hasSource = activations.getValue(i-1).isSourceFor(edgeInstance);
i = i + 1;
}
return hasSource;
In Figure 8.28, add the (overriding) operation “isSourceFor(edgeInstance: ActivityEdgeInstance): Boolean” to the class StructuredActivityNodeActivation, and add the following specification for it in Subclause 8.5.3.2.4:
isSourceFor(edgeInstance: ActivityEdgeInstance): Boolean
// Returns true if this node is either the source for the given
// edgeInstance itself or if it contains the source in its
// activation group.
boolean isSource = super.isSourceFor(edgeInstance);
if (!isSource) {
isSource = this.activationGroup.hasSourceFor(edgeInstance);
}
return isSource;
Actions taken:
March 28, 2012: received issue
January 7, 2013: closed issue
Issue 17288: ExpansionRegionActivation does not reset its activationGroups (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.4.2.3 ExpansionRegionActivation
ExpansionRegionActivation creates a set of activation groups that it uses to run the contents of the expansion region for each input value. However, after an ExpansionRegionActivation fires, it does not clear its activationGroups attribute. This means that, if the same activation fires again (as might happen if it is within a loop), subsequent firings add additional activation groups to the set already created in previous firings. This results in spurious extra executions of the contents of the expansion region.
To avoid this, the statement “this.activationGroups.clear();” should be added before the loop in ExpansionRegionActivation::doStructuredActivity.
Resolution: agreed
Revised Text: In Subclause 8.5.4.2.3, in operation doStructuredActivity, before the statement “int n = this.inputExpansionTokens.getValue(0).tokens.size();” add the statement “this.activationGroups.clear();”.
Actions taken:
March 30, 2012: received issue
January 7, 2013: closed issue
Issue 17291: ForkNodeActivation does not clear its tokens on termination (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.2.2.11 ForkNodeActivation
Unlike other control nodes, a fork node actually holds forked tokens pending their acceptance by downstream nodes. Therefore, when a ForkNodeActivation terminates, it needs to clear its held tokens, similarly to an ObjectNodeActivation. It currently does not do this, which means, if it is fired repeatedly in a loop node, and not all of its held tokens are accepted on previous iterations, it will be spuriously holding extra tokens on subsequent iterations.
Adding the following overriding method to ForkNodeActivation is sufficient, because ActivityNodeActivation::clearTokens() repeatedly withdraws held tokens until none are left, which will work even for multiply forked tokens.
public void terminate() {
// Remove any offered tokens and terminate.
this.clearTokens();
super.terminate();
} // terminate
Resolution: agreed
Revised Text: In Figure 8.27, add the (overriding) operation “terminate()” to the class ForkNodeActivation, and add the following specification for it in Subclause 8.5.2.2.11:
terminate()
// Remove any offered tokens and terminate.
this.clearTokens();
super.terminate();
Actions taken:
April 6, 2012: received issue
January 7, 2013: closed issue
Issue 17298: ExpansionRegionActivation isReady condition is too strong (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.4.2.3 ExpansionRegionActivation
The specification for ExpansionRegionActivation::isReady() requires that each of the input expansion nodes for an expansion region have the same (non-zero) number of values offered to it before the expansion region can fire. In particular, this means that if an expansion region receives null tokens representing “empty collections”, then the expansion region will not fire. This may seem to be the same as having the expansion region fire and do nothing, except that, if the region does not actually fire, then it does not offer control tokens on any outgoing control flows and any node downstream of those flows will be inhibited from firing. This does not like a reasonable limiting case of expansion region semantics on “empty” collections, and, in fact, it seems to violate what would be expected from the semantics of expansion regions as described in the full UML spec.
The requirement for all input expansion nodes to have the same number of values also seems to strong, requiring careful sizing of all expansion inputs lest the region not be able to fire. Instead, the size of the smallest input collection could be used to govern the number of executions of the body of the expansion region, to insure there are parallel inputs available from each input expansion node for each body execution.
Resolution: agreed
Revised Text: In Section 8.5.4.2.3, in operation takeOfferedTokens, before the second for loop, add the statement:
int n = this.numberOfValues();
Within the second for loop, replace the statements
TokenSet tokenSet = new TokenSet();
tokenSet.tokens = expansionNodeActivation.takeTokens();
with
TokenList tokens = expansionNodeActivation.takeTokens();
TokenSet tokenSet = new TokenSet();
int j = 1;
while (j <= n) {
tokenSet.tokens.add(tokens.getValue(j-1));
j = j + 1;
}
Remove the (overriding) operation isReady (and remove it in Figure 8.29).
In operation runGroup, in the second for loop, replace the statement
groupInput.addToken(tokenSet.tokens
.getValue(activationGroup.index - 1));
with
if (tokenSet.tokens.size() >= activationGroup.index) {
groupInput.addToken(tokenSet.tokens
.getValue(activationGroup.index - 1));
}
And replace the entire specification for the operation numberOfValues with
// 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;
Actions taken:
April 10, 2012: received issue
January 7, 2013: closed issue
Issue 17299: LoopNodeActivation does not properly handle termination due to an activity final node (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.3.2.3 LoopNodeActivation
If an activity final node directly owned by a loop node fires, then the loop node should terminate. However, the loop node should still produce values on its output pins based on any computations that have happened so far. Currently, when such an activity final node fires, the enclosing loop node is indeed immediately terminated via a call to its terminate(), but this does not actually terminate the loop in LoopNodeActivation::doStructuredActivity(). That loop only terminates once the test part of the loop executes, producing a null value (since all its nodes will no longer be running), which is interpreted as false. Further, the prior call to terminate() removes all tokens from the output pins in the body part of the loop, meaning that they are no longer available to be moved to the output pins of the loop node. As a result, the loop node produces no output, even if outputs have been computed prior to the firing of the final node.
Resolution: Agreed. Note that the modification of ActivityFinalNodeActivation in the revised text below to use a terminateAll operation from StructuredActivityNodeActivation allows this new operation to be overridden in LoopNodeActivation to specify “last wishes before termination” functionality.
Revised Text: In Subclause 8.5.2.2.3 ActivityFinalNodeActivation, replace the specification for fire with
// Terminate the activity execution or structured node activation
// containing this activation.
Debug.println("[fire] Activity final node " + this.node.name + "...");
if (this.group.activityExecution != null) {
this.group.activityExecution.terminate();
} else {
this.group.containingNodeActivation.terminateAll();
}
In Subclause 8.5.3.2.4 StructuredActivityNodeActivation, replace the specification of the operation terminate with
// Terminate the execution of all contained node activations (which
// completes the performance of the structured activity node
// activation), and then terminate this node itself.
this.terminateAll();
super.terminate();
In Figure 8.28, add the operation “terminateAll()” to the class StructuredActivityNodeActivation, and add the following specification for it in Subclause 8.5.3.2.4:
terminateAll()
// Terminate the execution of all contained node activations (which
// completes the performance of the structured activity node
// activation).
this.activationGroup.terminateAll();
In Subclause 8.5.3.2.3, in operation doStructuredActivity, in the do loop, in the else part of the if statement following the comment “Run the loop”, replace the statement
continuing = this.runTest();
with
if (this.isRunning()) {
continuing = this.runTest();
}
After the if statement, replace the statement
this.activationGroup.terminateAll();
with
if (this.isRunning()) {
this.activationGroup.terminateAll();
} else {
continuing = false;
}
After the do loop, surround the final for loop with an if statement “if (this.isRunning()) { … }”.
In Figure 8.28, add the (overriding) operation “terminateAll()” to the class LoopNodeActivation, and add the following specification for it to Subclause 8.5.3.2.3:
terminateAll()
// Copy the values of the body outputs to the loop outputs, and then
// terminate all activations in the loop.
OutputPinList resultPins = ((LoopNode)this.node).result;
for (int i = 0; i < bodyOutputLists.size(); i++) {
Values bodyOutputList = bodyOutputLists.getValue(i);
OutputPin resultPin = resultPins.getValue(i);
this.putTokens(resultPin, bodyOutputList.values);
}
super.terminateAll();
Actions taken:
April 10, 2012: received issue
January 7, 2013: closed issue
Issue 17300: An activity final node should not fire if it is not offered any tokens (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclause: 8.5.2.2.3 ActivityFinalNodeActivation
ActivityFinalNodeActivation::fire(incomingTokens) currently terminates the activity node activation group containing the activity final node, even if incomingTokens is empty. This is normally not a problem, since fire is usually only called if at least one token has been offered. However, if the activity final node is in a loop node or a conditional clause with an incoming edge from the body of the loop node or clause, then, when the test for the loop node or clause is being executed, the body part is not yet activated. If the source of the incoming edge to the activity final node is a body part node that is not activated, then the edge will be ignored in determining whether the final node is enabled, resulting in the final node being considered enabled and, unless otherwise prevented, firing prematurely, terminating the enclosing loop node or conditional node.
Resolution: Agreed. Note that the revised text below also includes a check for the final node having no incoming edges at all (which is valid), so that, in this case, it will fire when enabled, even though it will have no incoming tokens.
Revised Text: In Subclause 8.5.2.2.3, in operation fire, surround the termination functionality in the if statement
if (incomingTokens.size() > 0 | this.incomingEdges.size() == 0) {
…
}
Actions taken:
April 10, 2012: received issue
January 7, 2013: closed issue
Issue 17311: Having a fork node as initial enabled node does not work (fuml-rtf)
Click here for this issue's archive.
Source: LieberLieber Software (Mrs. Tanja Mayerhofer, mayerhofer(at)big.tuwien.ac.at.)
Nature: Clarification
Severity: Minor
Summary: If a fork node is identified as initial enabled node in the method ActivityNodeActivationGroup.run(ActivityNodeActivationList), and the method ActivityNodeActivation.receiveOffer() is called for the ForkNodeActivation, the method ForkNodeActivation.fire(TokenList) does not produce any forked tokens (because there is no real incoming token for the fork node) and because of this, the method call this.sendOffers(forkedTokens) (last statement of the method ForkNodeActivationActivation.fire(TokenList)) does not result in offers sent to successor nodes but this should be possible.
Resolution: A fork node is required to have a single incoming edge (this is Constraint [1] under Subclause 12.3.30 ForkNode in the UML Superstructure spec, constraints from which also apply to fUML). The intent is that a fork node only generates forked tokens based on tokens offered to it on that one incoming edge.
More specifically, consider that the only way a fork node can be initially enabled (in fUML) is if the source for its one incoming edge is either outside the activity node activation group containing the fork node activation or it is in the same activation group but not yet activated.
The first case occurs when the fork node is contained a structured node but is the target of an edge crossing into the structured node from a source outside it. In this case, receiveOffer is called on the (enabled) fork node activation when the structured node fires, and this operation in turn calls takeOfferedTokens, which accepts any tokens offered on the incoming edge into the fork node. If tokens have been offered on that edge previously to the structured node firing, then the fork node activation will create forked tokens for them and offer them on the outgoing edges from the fork node. On the other hand, if no tokens have been offered, then the fork node activation does nothing further, which is correct.
The second case occurs when the fork node is part of a conditional node or a loop node and the source of the incoming edge is an action or pin within the same node. The executable nodes for a conditional or loop node are divided up into test and body parts, which are activated incrementally per the semantics of the containing nodes. Contained control nodes, however, are always activated unconditionally (or, in the case of a loop, on each iteration). If a fork node is thus activated before the source of its incoming edge is, then it is not possible for anything to have been offered on that edge yet and, therefore, it is correct that the fork node should not offer anything on its outgoing edges. If that source node is later activated and does eventually offer something on the edge to the fork node, then that will trigger another call to receiveOffer on the fork node activation, which will result in forked nodes being offered on outgoing edges as appropriate.
So, the current semantics for fork nodes are actually correct.
Revised Text:
None.
Disposition: Closed, No Change
Revised Text:
Actions taken:
April 16, 2012: received issue
January 7, 2013: closed issue
Issue 17312: DecisionNodeActivation can send offers to multiple outgoing edges (fuml-rtf)
Click here for this issue's archive.
Source: LieberLieber Software (Mrs. Tanja Mayerhofer, mayerhofer(at)big.tuwien.ac.at.)
Nature: Clarification
Severity: Minor
Summary: In the method DecisionNodeActivation.fire(TokenList), a token offer is sent to each outgoing edge for which the guard evaluates to true resulting in the execution of multiple successor nodes.
Only one successor node should receive an offer also if the guards of several outgoing edges evaluate to true.
Resolution: In Subclause 12.3.22 DecisionNode of the UML Superstructure specification, it says:
“Notice that the semantics only requires that the token [offered to a decision node] traverse one edge, rather than be offered to only one edge. Multiple edges may be offered the token, but if only one of them has a target that accepts the token, then that edge is traversed. If multiple edges accept the token and have approval from their targets for traversal at the same time, then the semantics is not defined.”
Thus, it is correct that an incoming token to a decision node is offered on all outgoing edges for which the guard is satisfied. In fUML, if multiple downstream targets then try to accept the offered token at the same time, the semantics is the same as in any case of contention for a token. Only one of the targets can actually accept the token – since a decision node does not duplicate tokens, there is only one token to be accepted. Which of the targets actually gets the token is indeterminate, however.
Revised Text:
None.
Disposition: Closed, No Change
Revised Text:
Actions taken:
April 16, 2012: received issue
January 7, 2013: closed issue
Issue 17314: Structured activity node activations do not wait for contained accept event action activations (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclauses: 8.5.2.2.5 ActivityNodeActivationGroup, 8.5.3.2.4 StructuredActivityNodeActivation, 8.6.4.2.1 AcceptEvent ActionActivation
When a structured activity node contains one or more accept even actions, then, when those actions are waiting for the reception of event occurrences, one would expect that the structured activity node as a whole would also be waiting, pending the triggering of the actions. As currently specified, when accept event action activation registers to wait for event dispatching, it is not considered to be complete. Nevertheless, once all such actions have registered, and all other contained in a structured activity node have completed, the running of the node activations in the activation group for the structured node finishes, and the structured activity node activation completes, allowing execution to continue to subsequent nodes. This is not correct; the structured activity node activation should essentially be suspended until all the accept event actions activations have actually completed.
Resolution: agreed
Revised Text: In Figure 8.26, add the operations “suspend()” and “resume()” to the class ActivityNodeActivation, and add the following specifications for them to Subclause 8.5.2.2.4:
suspend()
// Suspend this activation within the activation group that contains it.
this.group.suspend(this);
resume() {
// Resume this activation within the activation group that contains it.
this.group.resume(this);
In Figure 8.25, add an association from ActivityNodeActivationGroup to ActivityNodeActivation with end name suspendedActivations and multiplicity *, and add the following description of it to Subclause 8.5.2.2.5:
• suspendedActivations: ActivityNodeActivation [*]
Activity node activations in this activation group that are suspended waiting for an event occurrence. If an activation group has a containing node activation and any suspended activations, then the containing node activation will also be suspended.
In Figure 8.25, add the operations “isSuspended(): Boolean”, “suspend(activation: ActivityNodeActivation)” and “resume(activation: ActivityNodeActivation)” to the class ActivityNodeActivationGroup, and add the following specifications for them to Subclause 8.5.2.2.5:
isSuspended(): Boolean
// Check if this activitation group has any suspended activations and is,
// therefore, itself suspended.
return this.suspendedActivations.size() > 0;
suspend(activation: ActivityNodeActivation)
// Suspend the given activation in this activation group. If this is
// the only suspended activation, and the activation group has a
// containing node activation, then suspend that containing activation.
if (!this.isSuspended()) {
StructuredActivityNodeActivation containingNodeActivation = this.containingNodeActivation;
if (containingNodeActivation != null) {
containingNodeActivation.suspend();
}
}
this.suspendedActivations.addValue(activation);
resume(activation: ActivityNodeActivation)
// Resume the given activation by removing it from the suspended
// activation list for this activation group. If this is the last
// suspended activation, and the activation group has a containing
// node activation, then resume that containing activation.
boolean found = false;
int i = 1;
while (!found & i <= this.suspendedActivations.size()) {
if (this.suspendedActivations.get(i-1) == activation) {
this.suspendedActivations.removeValue(i-1);
found = true;
}
i = i + 1;
}
if (!this.isSuspended()) {
StructuredActivityNodeActivation containingNodeActivation = this.containingNodeActivation;
if (containingNodeActivation != null) {
containingNodeActivation.resume();
}
}
In Figure 8.28, add the operations “isSuspended(): Boolean”, “completeAction(): Token[*]” and “resume()” to the class StructuredActivityNodeActivation, and add the following specifications for them in Subclause 8.5.3.2.4:
isSuspended(): Boolean
// Check if the activation group for this node is suspended.
return this.activationGroup.isSuspended();
completeAction(): Token[*]
// Only actually complete this structured activity node if it is not
// suspended.
TokenList incomingTokens = new TokenList();
if (!this.isSuspended()) {
incomingTokens = super.completeAction();
}
return incomingTokens;
resume()
// Only actually complete this structured activity node if it is not
// suspended.
TokenList incomingTokens = new TokenList();
if (!this.isSuspended()) {
incomingTokens = super.completeAction();
}
return incomingTokens;
In Section 8.6.2.2.1 ActionActivation, in the operation fire, replace the body of the specification after the initial comment block with
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);
In Figure 8.31, add the operation “completeAction():Token[*]” to the class ActionActivation, and add the following specification for it in Section 8.6.2.2.1:
completeAction(): Token[*]
// 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;
In Subclause 8.6.4.2.1 AcceptEventActionActivation, in the accept operation, in the if statement, after “this.receiveOffer()”, add the statement:
this.resume();
In the fire operation, at the end of the specification, add the statement:
this.suspend();
Actions taken:
April 16, 2012: received issue
January 7, 2013: closed issue
Discussion:
Issue 17345: Correction to the resolution of Issue 17209 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.3.2.2.11 Link
The resolution to Issue 17209 (Error handling creation and destruction of links of associations with ordered ends) included the addition of an addTo operation to the Link class. The specification of this new operation contains the statement:
FeatureValue otherFeatureValue = featureValues.getValue(j);
This should, instead, have been:
FeatureValue otherFeatureValue = otherFeatureValues.getValue(j);
Also, the resolution didn’t not the need to update Figure 8.12 to reflect the addition to Link of the operations isMatchingLink, getOtherFeatureValues and addTo, and the removal of the operation getFeatureValue.
Resolution: agreed
Revised Text: In Subclause 8.3.2.2.11, in the addTo operation, replace the statement
FeatureValue otherFeatureValue = featureValues.getValue(j);
with
FeatureValue otherFeatureValue = otherFeatureValues.getValue(j);
In Figure 8.12, add the following operations to the Link class:
isMatchingLink(link : ExtensionalValue, end : Property) : Boolean
getOtherFeatureValues(extent : ExtensionalValueList[*], end : Property) : FeatureValue[*]
addTo(Locus locus)
and remove the operation getFeatureValue.
Actions taken:
April 29, 2012: received issue
January 7, 2013: closed issue
Issue 17346: Read link actions and read structural feature actions do not handle ordered ends correctly (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.6.3.2.9 ReadLinkActionActivation, 8.6.3.2.13 StructuralFeatureActionActivation
Read link actions and read structural feature actions do not always return the values for an ordered association end in the correct order. In ReadLinkActionActivation::doAction, after the loop searching for the position at which to insert a featureValue, the statement
featureValues.addValue(k-1, featureValue);
should be replaced with
if (continueSearching) {
featureValue.addValue(featureValue);
} else {
featureValue.addValue(k-1, featureValue);
}
in order to correctly handle the case in which the featureValue should be added at the end of the list.
There is a similar statement in StructuralFeatureActionActivation::getMatchingLinks to insert a link at the correct position in the list of matching links, and it should be replaced in a similar manner to the above.
Resolution: agreed
Revised Text: In Subclause 8.6.3.2.9, in the doAction operation, within the first for loop, after the while loop, replace the statement
featureValues.addValue(k-1, featureValue);
with
if (continueSearching) {
featureValue.addValue(featureValue);
} else {
featureValue.addValue(k-1, featureValue);
}
In Subclause 8.6.3.2.13, in the getMatchingLinks operation, after the while loop, replace the statement
links.addValue(j–1, (Link)link);
with
if (continueSearching) {
links.addValue((Link)link);
} else {
links.addValue(j–1, (Link)link);
}
Actions taken:
April 29, 2012: received issue
January 7, 2013: closed issue
Issue 17391: Error in setting result pin values for CallActions (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.6.2.2.2 CallActionActivation
At the end of CallActionActivation::doAction, the output parameter values from the call execution are placed on the result output pins of the call action. However, the current specification presumes that the parameter values from the execution will be in the same order as the output parameters (and output pins). But this will not always be the case.
For example, if a parameter is an inout parameter, then it will have a parameter value added to the execution with its input before the execution is executed. It’s output will then be written to this existing output parameter value, while parameter values for out parameters will be created ordered after the one for the inout parameter, even if the out parameters are ordered before the inout parameter. Thus, the wrong values will be copied to the output pins.
Instead of relying on ordering, the specification for doAction should us the parameter reference for each output parameter value to identify the correct result output pin to which the parameter value should be written.
Resolution: agreed
Revised Text: In Subclause 8.6.2.2.2, in the doAction operation, near the end, replace the text
for (int j = 0; j < outputParameterValues.size(); j++) {
ParameterValue outputParameterValue = outputParameterValues.getValue(j);
OutputPin resultPin = resultPins.getValue(j);?
this.putTokens(resultPin, outputParameterValue.values);
}
with
pinNumber = 1;
i = 1;
while (i <= parameters.size()) {
Parameter parameter = parameters.getValue(i - 1);
if ((parameter.direction == ParameterDirectionKind.inout)
| (parameter.direction == ParameterDirectionKind.out)
| (parameter.direction == ParameterDirectionKind.return_)) {
for (int j = 0; j < outputParameterValues.size(); j++) {
ParameterValue outputParameterValue = outputParameterValues.getValue(j);
if (outputParameterValue.parameter == parameter) {
OutputPin resultPin = resultPins.getValue(pinNumber - 1);
this.putTokens(resultPin, outputParameterValue.values);
}
}
pinNumber = pinNumber + 1;
}
i = i + 1;
}
Actions taken:
May 23, 2012: received issue
January 7, 2013: closed issue
Issue 17392: Addition to resolution to Issue 17299 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.5.2.2.3 ActivityFinalNodeActivation
The resolution to Issue 17299 did not take into account, in the revision to ActivityFinalNodeActivation::fire, that the group for the ActivityFinalNodeActivation may be an ExpansionActivationGroup, which has a regionActivation property set instead of containingNodeActivation.
Resolution: Agreed. In addition to modifying ActivityFinalNodeActivation, to call the terminate operation on an enclosing expansion region, it is necessary to modify the ExpansionRegionActivation to fire the outputs of the expansion region before it terminates (which is the problem identified in Issue 17299).
(Note that the resolution to Issue 17300 also modified the ActivityFinalNodeActivation::fire operation.)
Revised Text: In Subclause 8.5.2.2.3, in the fire operation, replace the if statement, as introduced by the resolution to Issue 17299 and further modified by the resolution to Issue 17300, with
if (incomingTokens.size() > 0 | this.incomingEdges.size() == 0) {
if (this.group.activityExecution != null) {
this.group.activityExecution.terminate();
} else if (this.group.containingNodeActivation != null) {
this.group.containingNodeActivation.terminateAll();
} else if (this.group instanceof ExpansionActivationGroup){
((ExpansionActivationGroup)this.group).regionActivation.terminate();
}
}
In Subclause 8.5.4.2.3, in operation terminate
• In the terminate operation, replace the statement
activationGroup.terminateAll();
with
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();
• In the runGroup operation, surround the existing body of the operation with the if statement “if (this.isRunning()) { … }”. Further surround the statements after (but not including) the statement “activationGroup.run(activationGroup.nodeActivations);” with a similar if statement. (Note: the resolution to Issue 17499 proposes a further modification to this operation.)
Actions taken:
May 23, 2012: reeived issue
January 7, 2013: closed issue
Issue 17396: Errors in ReduceActionActivation::doAction (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.6.4.2.6 ReduceActionActivation
The specification for ReduceActionActivation::doAction has a number of errors.
1. The test “input1 != null” should be “input1 == null”.
2. The test for “parameter.direction == ParameterDirectionKind.out” should also test for a parameter direction of return.
3. After the execution of the reducer behavior, parameterValue1 should not be set to the resulting ParameterValue. Instead, only parameterValue1.values should be set to the resulting values (parameterValue1.parameter should remain unchanged as being equal to input1).
4. There is no abstract syntax constraint that the output of the reducer cannot be empty. The semantics for a reduce action should take into account the possibility of the reducer returning no value and not try to feed an empty input into the next reducer call.
Resolution: Agreed. A reasonable approach for dealing with the reducer returning an empty value is to simply start the reduction computation over with the remaining values in the list.
Revised Text: In Subclause 8.6.4.2.6, in the doAction operation:
1. Nested within the first while loop, change the condition “input1 != null” to “input1 == null”.
2. Also nested within the first while loop, change the condition “parameter.direction == ParameterDirectionKind.out” to “parameter.direction == ParameterDirectionKind.out | parameter.direction == ParameterDirectionKind.return_”.
3. Within the second while loop, change the statement
parameterValue1 = this.currentExecution.getParameterValue(output);
to
parameterValue1.values = this.currentExecution.getParameterValue(output).values;
4. Within the second while loop, after the statement “j = j + 1”, add:
if (parameterValue1.values.isEmpty() & j <= values.size()) {
parameterValue1.values.add(values.getValue(j - 1));
j = j + 1;
}
Actions taken:
May 25, 2012: received issue
January 7, 2013: closed issue
Issue 17397: Null tokens are not sent on by control nodes (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.5.2.2.15 ObjectNodeActivation
When an object node has no tokens, ObjectNodeActivation::sendOffers creates a null token to send. However, the holder attribute of this token is not set. This means that, even though the token gets offered, when a node tries to take it from the offering edge instance, the token is considered to have been withdrawn and is not passed on to the token. The effect of this is, in particular, that control node activations will never pass on null tokens, which is incorrect.
To avoid this, sendOffers should set the holder of the null token to be the object node sending it.
Resolution: agreed
Revised Text: In Subclause 8.5.2.2.15, in the sendOffers operation, replace the statement
tokens.addValue(new ObjectToken());
with
ObjectToken token = new ObjectToken();
token.holder = this
tokens.addValue(token);
Actions taken:
May 28, 2012: received issue
January 7, 2013: closed issue
Issue 17499: Conditional node and loop node activations do not wait for contained accept event action activations (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01)
Subclauses: 8.5.3.2.2 ConditionalNodeActivation, 8.5.3.2.3 LoopNodeActivation, 8.5.4.2.3 ExpansionRegionActivation
The resolution to Issue 17314 (Structured activity node activations do not wait for contained accept event action activations), on adopted on Ballot 2 of the fUML 1.1 RTF, works for plain structured activity nodes, but it does not work for structured activity nodes that are conditional nodes, loop nodes or expansion regions. For conditional nodes, the resumption of suspension of the node must take place in the context of a specific conditional clause. For loop nodes, resumption must allow continued iteration of the loop, rather than just completion of the node activation. For expansion regions, resumption must take place in the context of a specific expansion activation group.
Resolution: Agreed.
In order to simplify the resolution, it seems unnecessary to allow accept event actions within the test parts of conditional node clauses or loop nodes. Such tests are supposed to be “side effect free” and waiting for an external event to happen is essentially a non-functional side effect. If accept event actions are not allowed in tests, then, for a conditional node, suspension and resumptiuon can only happen in the body of a selected clause with a true test and, for a loop node, it can only happen in the body of the loop.
Revised Text: (Note: The revisions given here presume the revisions given in the resolution to Issue 17314.)
In Subclause 7.5.4.1, Figure 7.37, add a note to ReduceAction with the body “An accept event action may not be contained directly or indirectly in the test part of a clause or loop node.”
In Subclause 7.5.4.2.1 AcceptEventAction, add the following under “Additional Constraints”:
[4] fUML_no_accept_event_action_in_tests
An accept event action may not be contained directly or indirectly in the test part of a clause or loop node.
self->closure(inStructuredNode.oclAsType(ActivityNode))->forAll(n |
let s : StructuredActivityNode = n.inStructuredNode in
s->notEmpty() implies
(s.oclIsType(ConditionalNode) implies s.clause.test->excludes(n) and
s.oclIsType(LoopNode) implies s.test->excludes(n)))
In Subclause 8.5.3.1, Figure 8.28:
• In the class ConditionalNodeActivation, add the following operations:
completeBody()
completeAction(): Token[*]
resume()
• In the class LoopNodeActivation, add the following operations:
doLoop(continuing : Boolean)
saveBodyOutputs()
resume()
continueLoop()
In Subclause 8.5.3.2.2 ConditionalNodeActivation:
• At then end of the operation doStructuredActivity, remove the following statements:
OutputPinList resultPins = node.result;
OutputPinList bodyOutputPins = selectedClause.bodyOutput;
for (int k = 0; k < resultPins.size(); k++) {
OutputPin resultPin = resultPins.getValue(k);
OutputPin bodyOutputPin = bodyOutputPins.getValue(k);
this.putTokens(resultPin, this.getPinValues(bodyOutputPin));
}
• Add the following operations:
completeBody()
// Complete the activation of the body of a conditional note by
// copying the outputs of the selected clause (if any) to the output
// pins of the node and terminating the activation of all nested nodes.
if (this.selectedClause != null) {
ConditionalNode node = (ConditionalNode) (this.node);
OutputPinList resultPins = node.result;
OutputPinList bodyOutputPins = this.selectedClause.bodyOutput;
for (int k = 0; k < resultPins.size(); k++) {
OutputPin resultPin = resultPins.getValue(k);
OutputPin bodyOutputPin = bodyOutputPins.getValue(k);
this.putTokens(resultPin, this.getPinValues(bodyOutputPin));
}
}
this.activationGroup.terminateAll();
completeAction() : Token[0..*]
// Only complete the conditional node if it is not suspended.
if (!this.isSuspended()) {
completeBody();
}
return super.completeAction();
resume()
// When this conditional node is resumed after being suspended, complete
// its body and then resume it as a structured activity node.
// [Note that this presumes that accept event actions are not allowed
// in the test part of a clause of a conditional node.]
completeBody();
super.resume();
In Subclause 8.5.3.2.3 LoopNodeActivation:
• At the end of the operation doStructuredActivity, replace the statements from “boolean continuing = true;” to the end of the operation specification with the single statement
this.doLoop(true);
• At the end of the operation runBody, replace the statements
OutputPinList bodyOutputs = loopNode.bodyOutput;
ValuesList bodyOutputLists = this.bodyOutputLists;
for (int i = 0; i < bodyOutputs.size(); i++) {
OutputPin bodyOutput = bodyOutputs.getValue(i);
Values bodyOutputList = bodyOutputLists.getValue(i);
bodyOutputList.values = this.getPinValues(bodyOutput);
}
with
if (!this.isSuspended()) {
this.saveBodyOutputs();
}
• Add the following operations:
doLoop(in continuing : Boolean)
// If isTestedFirst is true, then repeatedly run the test part and the
// body part of the loop, copying values from the body outputs to the
// loop variables.
// If isTestedFirst is false, then repeatedly run the body part and the
// test part of the loop, copying values from the body outputs to the
// loop variables.
LoopNode loopNode = (LoopNode) (this.node);
OutputPinList loopVariables = loopNode.loopVariable;
OutputPinList resultPins = loopNode.result;
while (continuing) {
// Set loop variable values
this.runLoopVariables();
for (int i = 0; i < loopVariables.size(); i++) {
OutputPin loopVariable = loopVariables.getValue(i);
Values bodyOutputList = bodyOutputLists.getValue(i);
ValueList values = bodyOutputList.values;
this.putPinValues(loopVariable, values);
((OutputPinActivation) this.activationGroup
.getNodeActivation(loopVariable)).sendUnofferedTokens();
}
// Run all the non-executable, non-pin nodes in the conditional
// node.
ActivityNodeActivationList nodeActivations = this.activationGroup.nodeActivations;
ActivityNodeActivationList nonExecutableNodeActivations =
new ActivityNodeActivationList();
for (int i = 0; i < nodeActivations.size(); i++) {
ActivityNodeActivation nodeActivation = nodeActivations
.getValue(i);
if (!(nodeActivation.node instanceof ExecutableNode |
nodeActivation.node instanceof Pin)) {
nonExecutableNodeActivations.addValue(nodeActivation);
}
}
this.activationGroup.run(nonExecutableNodeActivations);
// Run the loop
if (loopNode.isTestedFirst) {
continuing = this.runTest();
if (continuing) {
this.runBody();
}
} else {
this.runBody();
if (this.isRunning() & !this.isSuspended()) {
continuing = this.runTest();
}
}
if (this.isRunning() && !this.isSuspended()) {
this.activationGroup.terminateAll();
} else {
continuing = false;
}
Debug.println("[doStructuredActivity] "
+ (continuing? "Continuing." :
this.isSuspended()? "Suspended":
"Done."));
}
if (this.isRunning() && !this.isSuspended()) {
for (int i = 0; i < bodyOutputLists.size(); i++) {
Values bodyOutputList = bodyOutputLists.getValue(i);
OutputPin resultPin = resultPins.getValue(i);
this.putTokens(resultPin, bodyOutputList.values);
}
}
saveBodyOutputs()
// Save the body outputs for use in the next iteration.
LoopNode loopNode = (LoopNode) this.node;
OutputPinList bodyOutputs = loopNode.bodyOutput;
ValuesList bodyOutputLists = this.bodyOutputLists;
for (int i = 0; i < bodyOutputs.size(); i++) {
OutputPin bodyOutput = bodyOutputs.getValue(i);
Values bodyOutputList = bodyOutputLists.getValue(i);
bodyOutputList.values = this.getPinValues(bodyOutput);
}
resume()
// When this loop node is resumed after being suspended, continue with
// its next iteration (if any). Once the loop has completed execution
// without being suspended again, complete the action.
LoopNode loopNode = (LoopNode) (this.node);
this.saveBodyOutputs();
if (loopNode.mustIsolate) {
_beginIsolation();
this.continueLoop();
_endIsolation();
} else {
this.continueLoop();
}
if (this.isSuspended()) {
// NOTE: If the subsequent iteration of the loop suspends it again,
// then it is necessary to remove the previous suspension from the
// containing activity node activation group.
this.group.resume(this);
} else {
super.resume();
}
continueLoop()
// Continue the loop node when it is resumed after being suspended. If
// isTestedFirst is true, then continue executing the loop. If
// isTestedFirst is false, then run the test to determine whether
// the loop should be continued or completed.
// [Note that this presumes that an accept event action is not allowed
// in the test part of a loop node.]
LoopNode loopNode = (LoopNode) (this.node);
boolean continuing = true;
if (!loopNode.isTestedFirst) {
continuing = this.runTest();
}
if (this.isRunning()) {
this.activationGroup.terminateAll();
this.doLoop(continuing);
}
In Subclause 8.5.4.1, Figure 8.29:
• In class ExpansionActivationGroup, add the following operations:
suspend(activation : ActivityNodeActivation)
resume(activation : ActivityNodeActivation)
• In class ExpansionRegionActivation, add the attribute:
next : Integer [0..1]
and the following operations:
runIterative()
runParallel()
doOutput()
terminateGroup(activationGroup : ExpansionActivationGroup)
isSuspended() : Boolean
resume(activationGroup : ExpansionActivationGroup)
In Subclause 8.5.4.2.1 ExpansionActivationGroup, add the following operations:
suspend(in activation : ActivityNodeActivation)
// Suspend the given activation in this activation group. If this is
// the only suspended activation, then suspend the associated region
// activation.
if (!this.isSuspended()) {
this.regionActivation.suspend();
}
super.suspend(activation);
resume(in activation : ActivityNodeActivation)
// Resume the given activation in this activation group. If this is the
// last suspended activation, then resume the associated region
// activation.
super.resume(activation);
if (!this.isSuspended()) {
this.regionActivation.resume(this);
}
In Subclause 8.5.4.2.3 ExpansionRegionActivation:
• Under “Attributes” replace “None” with
• next : Integer [0..1]
The index of the next activation group to be run, if the expansion region is iterative.
• In the doStructuredActivity operation:
o In the first branch of the if statement near the end, replace the statements
for (int i = 0; i < activationGroups.size(); i++) {
ExpansionActivationGroup activationGroup = activationGroups
.getValue(i);
this.runGroup(activationGroup);
}
with the statements
this.next = 1;
this.runIterative();
o In the second branch of the if statement, replace the statements
// *** Activate all groups concurrently. ***
for (Iterator i = activationGroups.iterator(); i.hasNext();) {
ExpansionActivationGroup activationGroup = (ExpansionActivationGroup) i
.next();
this.runGroup(activationGroup);
}
with the single statement
this.runParallel();
o Replace the for loop at the end with the single statement
this.doOutput();
• In the runGroup operation, replace the following statements (as already modified per the resolution to Issue 17392)
if (this.isRunning()) { // Added
OutputPinActivationList groupOutputs = activationGroup.groupOutputs;
for (int i = 0; i < groupOutputs.size(); i++) {
OutputPinActivation groupOutput = groupOutputs.getValue(i);
groupOutput.fire(groupOutput.takeOfferedTokens());
}
activationGroup.terminateAll();
}
with
this.terminateGroup(activationGroup);
• Add the following operations:
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;
}
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);
}
doOutput()
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());
}
}
}
terminateGroup(in activationGroup : ExpansionActivationGroup)
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();
}
isSuspended() : Boolean
// 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;
resume(in activationGroup : ExpansionActivationGroup)
// 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();
Actions taken:
July 13, 2012: received issue
January 7, 2013: closed issue
Discussion:
Issue 17502: Specification of ClassifierBehaviorExecution and ObjectActivation are not consistent with Annex A (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML), v1.0 (formal/2011-02-02)
Subclause: 8.4.3.2.1 ClassifierBehaviorExecution, 8.4.3.2.5 ObjectActivation
Subclause A.3.7 establishes the Java notation “_startObjectBehavior();” as mapping to a start object behavior action, not an operation call, and it also states that “A class may not define a user operation called ‘_startObjectBehavior.’” However, in Subclause 8.4.3.1, Figure 8.17, _startObjectBehavior is shown as an operation on both ClassifierBehaviorExecution and ObjectActivation, and it is specified in as an operation for these classes in Subclauses 8.4.3.2.1 and 8.4.3.2.5.
Subclause A.3.8 establishes the Java notation “_send(new <signal>());” as mapping to a send signal action, not an operation call. However, in Figure 8.17, _send is shown as an operation of ObjectActivation, and it is specified as an operation in Subclause 8.4.3.2.5.
Resolution: Agreed. Note also that the activity shown in Figure 8.18 has a call to _startObjectBehaviorAction and the activity shown in Figure 8.19 has a call to _send.
Revised Text: In Subclause 8.4.3.1, Figure 8.17:
• In the class ClassifierBehaviorExecution, remove the operation _startObjectBehavior.
• In the class ObjectActivation, remove the operations _startObjectBehavior and _send.
In Subclause 8.4.3.2.1:
• In Figure 8.18, replace the call operation action “Call _startObjectBehavior” with a read structural feature action for the feature “execution”, the result of which feeds into a call operation action for the operation “execute”.
• Remove the specification for the operation _startObjectBehavior.
In Subclause 8.4.3.2.5:
• In Figure 8.19, replace the call operation action “Call _send” with a call to the operation “dispatchNextEvent” (which does not take any arguments).
• Remove the specifications for the operations _startObjectBehavior and _send.
Actions taken:
July 16, 2012: received issue
January 7, 2013: closed issue
Issue 17557: Addition to the resolution to fUML Issue 15987 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: The resolution to Issue 15987 (The fUML Foundational Model Library should support the new UML 2.4 Real primitive type) adds LiteralReal and LiteralRealEvaluations class, but neglects to update the ExecutionFactoryL1::instantiateVisitor operation to instatiate an instance of the latter class when given an instance of the former.
Resolution: agreed
Revised Text: In Subclause 8.2.2.2.3 ExecutorL1, in the specification for the instantiateVisitor operation, after the statement “return visitor;” add
else if (element instanceof fUML.Syntax.Classes.Kernel.LiteralReal) {
visitor = new LiteralRealEvaluation();
}
Actions taken:
August 21, 2012: received issue
January 7, 2013: closed issue
Issue 17558: Addition to the resolution of fUML Issue 17203 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: The resolution to Issue 17203 (Bug in ForkedToken::withdraw when the baseToken is a ForkedToken) adds a Boolean baseTokenIsWithdrawn attribute to the ForkedToken class. However, since bUML (like fUML) does not support default values on attributes, this attribute needs to be explicitly set to false when a ForkedToken is created in ForkedNodeActivation::fire(). The resolution neglects to include this revision.
Resolution: agreed
Revised Text: In Subclause 8.5.2.2.11 ForkNodeActivation, in operation fire, in the for loop, after the statement “forkedToken.remainingOffersCount = outgoingEdgeCount;”, add
token.baseTokenIsWithdrawn = false;
Actions taken:
August 21, 2012: received issue
January 7, 2013: closed issue
Issue 17559: Correction to the resolution to fUML Issue 17209 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: The Revised Text instructions in the resolution to Issue 17209 (Error handling creation and destruction of links of associations with ordered ends) includes the statement “Remove the (overriding) operation getFeatureValue.” However, Link does not have an overriding getFeatureValue operation. The correct instruction is to remove the setFeatureValue operation.
Resolution: agreed
Revised Text: In Subclause 8.3.2.1, Figure 8.12, and in Subclause 8.3.2.2.11, remove the (overriding) operation setFeatureValue
Actions taken:
August 21, 2012: received issue
January 7, 2013: closed issue
Issue 17560: Addition to the resolution to fUML Issue 17499 (fuml-rtf)
Click here for this issue's archive.
Source: Ivar Jacobson International AB (Mr. Ed Seidewitz, eseidewitz(at)ivarjacobson.com)
Nature: Uncategorized Issue
Severity:
Summary: The resolution to Issue 17499 (Conditional node and loop node activations do not wait for contained accept event action activations) removes some lines from the specification for the operation ConditionalNodeActivation::doStructuredActivity. However, it neglects to state to remove the final line “this.activationGroup.terminateAll();”, which also needs to be removed.
Resolution: Agreed. In addition, the selectedClause attribute needs to be set to null before the if statement that tests if there are any clauses to select, since this is tested in the new completeBody operation. Otherwise, selectedClause could contain a spurious value from a previous activation of the conditional node, causing completeBody to try to copy outputs from that clause, rather than just doing the terminateAll call.
Revised Text: In Subclause 8.5.3.2.2 ConditionalNodeActivation, in operation doStructuredActivity (as modified by the resolution to Issue 17499):
• Before the if statement with the condition “this.selectedClauses.size() > 0 & this.isRunning()”, add the statement “this.selectedClause = null;”
• Remove the final line “this.activationGroup.terminateAll();”.
Actions taken:
August 21, 2012: received issue
January 7, 2013: closed issue