Issue 19845: Introduce CallEvent, AcceptCallAction and ReplyAction to keep consistency with PSSM (fuml-rtf) Source: Fraunhofer FOKUS (Mr. Marc-Florian Wendland, marc-florian.wendland(at)fokus.fraunhofer.de) Nature: Revision Severity: Significant Summary: fUML shall introduce CallEvent, AcceptCallAction and ReplyAction into fUML and harmonize their semantics with the "fragmented method" paradigm of state machines (and PSSM). In fact, the handling of CallEvents should be the same as the handling of SignalEvents in fUML. This would mean that CallOperationActions do not any longer result in the execution of the method Behavior of an Operation, but in the generation of a CallEvent that is put into the event pool of the target object of the CallOperationAction. This would also require to not permit Operations to contain method - this would be then in synch with Reception. AcceptCallAction should be introduced, or AcceptEventAction should be relaxed to specify Trigger that refer to CallEvents. In addition, ReplyActions shall be included in order to finally send the result of the execution of the Operation. Resolution: Add CallEvent, AcceptCallAction and ReplyAction To disallow the use of methods to implement operations, as suggested in the issue description, would be a major backward incompatibility with previous versions of fUML and a radical departure from typical object-oriented practice. It would also essentially require all classes to be active, since only active objects have event pools and can react to event occurrences. Finally, it would require that the fUML execution model be completely rewritten, along with its base semantics, since it currently uses an OO style in which (concrete) operations always have methods. On the other hand, the Precise Semantics of State Machines (PSSM) specification (as submitted) adds the ability for state machines to handle call events, as an alternative to, not a replacement for, using methods to implement operations. But the generic handling of operations via call events (as described in the UML 2.4.1/2.5 semantics) is not really specific to state machines. So it is reasonable to suggest that this capability would be better incorporated into the common behavior semantics of fUML, rather than only being available when a tool conforms to PSSM. Indeed, the PSSM alpha specification gets around the lack of support for call events in the fUML common semantics by introducing a specialization of the RedefinitionBasedDispatchStrategy class that returns a special kind of Execution when a call is to be handled using a call event. However, this means that any tool using an alternative dispatch strategy would also need to have a specialization of that strategy that is similarly modified to be able to handle calls using call events ? but only for use when PSSM is supported. It would clearly be better if any properly specified dispatch strategy would automatically work whether a call ended up being handled by a method or by a call event occurrence. Further, the PSSM alpha specification uses a "spin loop" (i.e., a loop that continually checks the value of a semaphore, which is expected to be reset by a concurrent process) to specify the blocking of a caller while it waits for a call event occurrence to be handled by the target object. This is problematic, since the fUML concurrency semantics do not guarantee that any one executing process allow any other process to execute, except at a "wait point" (such as an accept event action). This means that, as currently specified in PSSM, it would be a legal execution trace for a "blocked" caller to continually execute its loop, without allowing the target object classifier behavior to ever execute to handle the call event occurrence, so the call would never complete. Any alternative to using a "spin loop" blocking approach would need to be incorporated directly into the fUML common behavior semantics. Unfortunately, to do so would require a major change to the handling of synchronous calls in general. This is because, even if a behavior is itself invoked directly, whether via a direct call or as an operation method, it could (directly or indirectly) call an operation that is handled using a call event occurrence. Thus, the execution model would have to take into account that, on any call action or other synchronous behavior execution, the call might have to block for an arbitrarily long amount of time (or forever), waiting while some call event occurrence remains unhandled. One way to handle this would be by specifying that output parameter values from any behavior execution be delivered via a "call back" mechanism. A caller would provide a "continuation" object when calling the execute operation on the behavior execution, and output parameter values from the invocation would be delivered by calling an operation on the provided object, rather than being set during the running of execute itself. Thus, if the call gets blocked waiting for the handling of a call event occurrence, the original execute call could return, with the caller only continuing once a call back is made to its continuation object (if ever). But this would be a major change to the fundamental approach for handling synchronous invocation in the fUML execution model, all the way up to the event accepter mechanism (since a run-to-completion step is essentially specified in the fUML execution model by making a synchronous call to an event accepter). And this would not only complicate the specification of fUML, it would also make it significantly more complicated to handle, e.g., the invocation of entry, exit and effect behaviors on state machines in PSSM. It is therefore not considered feasible to propose this approach in the context of an RTF issue resolution. Another possibility would be to introduce a mechanism into the base semantics, that is, the formal semantics of Base UML (bUML), in which the fUML execution model is written. However, in order to do this, it would be necessary to also extend bUML syntactically with a UML feature that could represent such blocking. For example, an accept event action could be used with a trigger for a change event on a semaphore attribute (which would avoid the need for a spin loop) or for a time event (which would allow a caller to "wait" for some period of time during an iteration of a spin loop, allowing other processes to execute). But one of the fundamental tenets of bUML is that it is a syntactic subset of fUML ? that is, the fUML execution model is itself a legal fUML model. That means that any new feature introduced into bUML would also need to be introduced into fUML. But both change events and time events have not been incorporated into fUML so far because of the difficulty in specifying their (general) functionality. So, again, it is not considered appropriate to attempt introducing this functionality simply to address an issue that did not even request that functionality specifically. Therefore, while this resolution does propose adding CallEvent, AcceptCallAction and ReplyAction to fUML, it specifies their semantics using an approach similar to that in the PSSM alpha specification, using a spin loop. However, a requirement is added, without further formal basis, that an execution trace that consists entirely of a caller executing a spin loop for all time is not allowed, unless no other execution trace is possible (i.e., no other non-blocked concurrent processes are available to execute). It is considered clear that this can be implemented in practice in any execution tool, evn in the absence of further formalization. However, it is also expected that the requirement will be more formally specified in a future major revision of fUML. Revised Text: Update the specification document as follows, and also make corresponding updates to the normative fUML Syntax and Semantics XMI files. (Note: This resolution presumes the resolution to issue [1]FUML13-25.) Clause 7 Abstract Syntax In 7.2.2.2.25 Operation, under Additional Constraints, replace the operation [1] zero_or_one_method with the following: [1] fUML_operation_has_at_most_one_method If an operation is abstract, it must have no method. Otherwise it must not have more than one method and it must have exactly one method unless owned by an active class. if self.isAbstract then self.method->isEmpty() else self.method->size() <= 1 and ((self.class = null or not self.class.isActive) implies self.method->size() = 1) endif In 7.3.2.1 Overview, in Figure 7.15 Common Behavior, replace the body of the comment on the class Operation with "If an operation is abstract, it must have no method. Otherwise it must not have more than one method and it must have exactly one method unless owned by an active class." In 7.3.3.1 Overview, in the bullet list after "From Events", remove the second bulleted item in the list. In Figure 7.18 Events, replace the diagram with: Add the following subclause, and renumber subsequent subclauses appropriately. 7.3.3.2.1 CallEvent Generalizations *MessageEvent Attributes None Associations *operation : Operation Additional Constraints [1] fUML_call_event_operation_has_no_method The operation of the call event must not have any methods. self.operation.method->isEmpty() In 7.5.4.1 Overview, in the bullet list following "From Accept Event Actions", remove the first two bulleted items. In Figure 7.35 Accept Event Actions, replace the diagram with: Editorial Note. Figure 7.35 is renumbered to 7.36 as a result of the resolution to issue [2]FUML13-4. Add the following subclause, and renumber subsequent subclauses appropriately. 7.5.4.2.1 AcceptCallAction Generalizations *AcceptEventAction Attributes None Associations *returnInformation : OutputPin Additional Constraints [1] fUML_accept_call_action_call_event_operations The operations of the call events on the triggers of an accept call action must be owned or inherited by the context class of the action. let cls: Class = self.context.oclAsType(Class) in let classes:Bag(Class) = cls.allParents()->select(oclIsKindOf(Class))->collect(oclAsType(Class))->union(cls->asBag()) in classes.ownedOperation->includesAll(self.trigger.event->collect(oclAsType(CallEvent)).operation) In 7.5.4.2.1 AcceptEventAction (7.5.4.2.2 as renumbered), under Additional Constraints, in constraint [2] fUML_only_signal_event_triggers, in the description, replace "All" with "Unless the action is an accept call action, all". Add the following to the beginning of the OCL: not self.oclIsKindOf(AcceptCallAction) implies. In constraint [3] fUML_receive_all_triggering_signals, in the description, replace "The" with "Unless the action is an accept call action, the". Add the following to the beginning of the OCL: not self.oclIsKindOf(AcceptCallAction). After 7.5.4.2.5 ReduceAction (7.5.4.2.6 as renumbered), add the following subclause, and renumber subsequent subclauses appropriately. 7.5.4.2.7 ReplyAction Generalizations *Action Attributes None Associations *replyToCall : Trigger *replyValue : InputPin [0..*] *returnInformation : InputPin Additional Constraints None Clause 8 Execution Model In 8.2.2.2.3 ExecutionFactoryL1, in the operation [1] instantiateVisitor, after the last else clause but before the return statement, add the following: else if (element instanceof CallEventBehavior) { visitor = new CallEventExecution(); } In 8.2.4.2.1 ExecutionFactoryL3, in the operation [1] instantiateVisitor, before else if(element instanceof AcceptEventAction), add the following: // Note: Since AcceptCallAction is a subclass of AcceptEventAction, // element must be tested against AcceptCallAction before // AcceptEventAction. else if (element instanceof AcceptCallAction) { visitor = new AcceptCallActionActivation(); } In 8.3.2.1 Overview, under Polymorphic Operation Dispatching, at the end of the first sentence, change "an abstract getMethod operation" to "a second operation, getMethod". After that paragraph, insert the following: It is also possible for a concrete operation to have no method, if calls to it are to be handled using a call event (see the discussion of accept call actions in 8.6.4). This case is still managed through the dispatch strategy. Instead of using a method behavior defined for the operation in the model, an instance of a special CallEventBehavior class (see 8.4.3) is created to act as an effective method for the call. For convenience, the getMethod operation in the DispatchStrategy superclass this functionality, which may be used as appropriate in the definition of the getMethod operation for a subclass of DispatchStrategy (for example, the redefinition based dispatch strategy getMethod operation calls the superclass operation if it identifies a concrete, most-redefined operation, but that operation does not have a method). The execution created for a call event behavior is an instance of the CallEventExecution class, which carries out the behavior of sending a call event occurrence and waiting for a response. In Figure 8.12 Structured Values, show the operation DispatchStrategy::getMethod as being concrete rather than abstract. In 8.3.2.2.4 Dispatch Strategy, under Operations, change the body of operation [3] getMethod to: // Get the method that corresponds to the given operation for the given object. // By default, the operation is treated as being called via a call event occurrence, // with a call even behavior as its effective method. Concrete dispatch strategy // subclasses may override this default to provide other dispatching behavior. CallEventBehavior method = new CallEventBehavior(); method.setOperation(operation); return method; In 8.3.2.2.22 RedefinitionBasedDispatchStrategy, replace the introductory description with the following: A redefinition-based dispatch strategy is one that requires an overriding subclass operation to explicitly redefine the overridden superclass operation. If a concrete operation has no methods, then it is assumed to be handled by a call event; otherwise, it should have at most one method. Under Operations, in the operation [1] getMethod, change the introductory comment to: // Find the member operation of a type of the given object that // is the same as or a redefinition of the given operation. Then // return the method of that operation, if it has one, otherwise // return a CallEventBehavior as the effective method for the // matching operation. // [If there is more than one type with a matching operation, then // the first one is arbitrarily chosen.] Replace the nested statement method = memberOperation.method.getValue(0); with if (memberOperation.method.size() == 0) { method = super.getMethod(object, memberOperation); } else { method = memberOperation.method.getValue(0); } In 8.4.3.1 Overview, under Event Dispatching, after the first paragraph, add the following: Note: Operations calls are always synchronous invocations in fUML, as opposed to signal sends, which are always asynchronous invocations. Nevertheless, when an operation call is handled by an active object via a call event, the call even occurrence is handled asynchronously by the object, in the sense discussed above. The synchronous nature of the call is maintained for the caller by requiring the caller to block the execution thread making the call until the call event occurrence is dispatched and replied to. See also the discussion of call event occurrences under Event Occurrences below. Under Event Occurrences, in the first paragraph, in the second sentence, change "two kinds of events" to "three kinds of events" and change "and signal reception events" to ", signal reception events and operation call events". In the fifth (last) paragraph, replace the third and following sentences with: Currently, a regular accept even action in fUML is limited to handling signal events, while an accept call action (a special kind of accept event action) is used to handle call events (see 8.6.4.2.1). When an event occurrence is received by an active object, it is placed in the event pool. When this event occurrence is dispatched, if there is a matching accept event action accepter for it, then it will be accepted by the accept event action (or accept call action, for a call event occurrence), resulting in the resumption of execution of the activity containing the action. After that paragraph, add the following new paragraph: As mentioned above under Event Dispatching, an operation call is always a synchronous invocation from the point of view of the caller, even if it is handled asynchronously using a call event at the target. In order to achieve this, a call event occurrence is always sent by executing a special call event execution object (see 8.4.3.2.2), after which the calling execution thread is blocked until a reply to the call is received. Blocking is specified in the suspend operation of the call event execution using a loop that repeatedly checks for the callSuspended flag to be reset by the concurrent thread responding to the call. The body of the loop consists of a call to a special wait operation, which does nothing but, during which, a conforming execution tool must allow other concurrent threads to run. That is, an execution trace that, after a certain point, consists entirely of a caller executing one or more suspend loops for all time is not allowed, unless no other execution trace is possible (i.e., no other non-blocked concurrent threads are available to execute). Note: The special rule above concerning waiting is necessary because fUML allows great flexibility in whether a conforming execution tool actually implements a concurrent thread as a parallel execution or not (see 2.4). Without this rule, it would be allowable for an conforming execution tool to consume all processing resources executing one or more suspend loops and never allow the execution of the dispatch loops necessary to handle the call event occurrences that have been sent. Even with the rule, however, it is not inherently guaranteed that any call event occurrence will ever be dispatched, since the dispatch loop of the target object that receive it may still be blocked forever, in a particular implementation, by some other non-suspended thread. In Figure 8.16 Event Occurrences, replace the diagram with: Editorial Note. This diagram also reflects changes made in the resolutions for issues [3]FUML13-1 and [4]FUML13-25. Under 8.4.3.2 Class Descriptions, add the following subclauses, and renumber subsequent subclauses appropriately: 8.4.3.2.1 CallEventBehavior A call event behavior is a special kind of behavior used to represent the type of a call event execution. It is not directly a part of a user model, but has a signature constructed from the signature of the operation being called. Generalizations *Behavior Attributes None Associations *operation : Operation The operation whose call is to be handled via a call event. Operations [1] setOperation ( in operation : Operation ) // Set the operation for this call event behavior and construct // the behavior signature based on the operation signature. this.operation = operation; for(int i = 0; i < operation.ownedParameter.size(); i++){ Parameter operationParameter = operation.ownedParameter.get(i); Parameter parameter = new Parameter(); parameter.name = operationParameter.name; parameter.type = operationParameter.type; parameter.multiplicityElement.lowerValue = operationParameter.multiplicityElement.lowerValue; parameter.multiplicityElement.lower = operationParameter.multiplicityElement.lower; parameter.multiplicityElement.upperValue = operationParameter.multiplicityElement.upperValue; parameter.multiplicityElement.upper = operationParameter.multiplicityElement.upper; parameter.direction = operationParameter.direction; parameter.owner = this; parameter.namespace = this; this.ownedElement.addValue(parameter); this.ownedMember.addValue(parameter); this.member.addValue(parameter); this.ownedParameter.addValue(parameter); } this.isReentrant = true; this.name = "CallEventBehavior"; if (operation.name != null) { this.name = this.name + "(" + operation.name + ")"; } Editorial Note. Using the operation EventOccurrence::sendTo in the operation CallEventExecution::makeCall below is consistent with the resolution to issue [5]FUML13-1. 8.4.3.2.2 CallEventExecution A call event execution acts as the effective method execution for an operation call that is to be handled by a call event. When executed, a call event execution sends a call event occurrence to the target object and then suspends until a reply is received. Generalizations *Execution Attributes *callerSuspended : Boolean Indicates whether the caller is suspended, waiting for a reply to the sent call event occurrence. Concurrently setting this flag to "false" releases the caller. Associations None Operations [1] copy ( ) : Value // Create a new call event execution that is a copy of this execution, with the // caller initially not suspended. CallEventExecution copy = (CallEventExecution)super.copy(); copy.callerSuspended = false; return copy; [2] createEventOccurrence ( ) : EventOccurrence // Create a call event occurrence associated with this call event execution. // (This operation may be overridden in subclasses to alter how the event // occurrence is create, e.g., if it is necessary to wrap it.) CallEventOccurrence eventOccurrence = new CallEventOccurrence(); eventOccurrence.execution = this; return eventOccurrence; [3] execute( ) // Make the call on the target object (which is the context of this execution) // and suspend the caller until the call is completed. // Note: The callerSuspended flag needs to be set before the call is made, // in case the call is immediately handled and returned, even before the // suspend loop is started. this.setCallerSuspended(true); this.makeCall(); this.suspendCaller(); [4] getInputParameterValues ( ) : ParameterValue[0..*] // Return input parameter values for this execution. ParameterValueList parameterValues = new ParameterValueList(); for(int i=0; i < this.parameterValues.size(); i++){ ParameterValue parameterValue = this.parameterValues.get(i); if(parameterValue.parameter.direction == ParameterDirectionKind.in | parameterValue.parameter.direction == ParameterDirectionKind.inout){ parameterValues.addValue(parameterValue); } } return parameterValues; [5] getOperation ( ) : Operation // Return the operation being called by this call event execution. return ((CallEventBehavior)this.getBehavior()).operation; [6] isCallerSuspended ( ) : Boolean // Check if the caller is still suspended. // This is done in isolation from possible concurrent updates to this flag. _beginIsolation(); boolean isSuspended = this.callerSuspended; _endIsolation(); return isSuspended; [7] makeCall ( ) // Make the call on the target object (which is the context of this execution) // by sending a call event occurrence. (Note that the call will never be // completed if the target is not an active object, since then the object // would then have no event pool in which the event occurrence could be placed.) Reference reference = new Reference(); reference.referent = this.context; this.createEventOccurrence().sendTo(reference); [8] new_ ( ) : Value // Create a new call event execution. return new CallEventExecution(); [9] releaseCaller ( ) // Release the caller, if suspended. this.setCallerSuspended(false); [10] setCallerSuspended ( in callerSuspended : Boolean ) // Set the caller suspended flag to the given value. // This is done in isolation from possible concurrent queries to this flag. _beginIsolation(); this.callerSuspended = callerSuspended; _endIsolation(); [11] setOutputParameterValues ( parameterValues : ParameterValue[0..*]) // Set the output parameter values for this execution. ParameterList parameters = this.getBehavior().ownedParameter; int i = 1; int j = 1; while (i <= parameters.size()) { Parameter parameter = parameters.get(i-1); if (parameter.direction == ParameterDirectionKind.inout | parameter.direction == ParameterDirectionKind.out | parameter.direction == ParameterDirectionKind.return_ ) { ParameterValue parameterValue = parameterValues.get(j-1); parameterValue.parameter = parameter; this.setParameterValue(parameterValue); j = j + 1; } i = i + 1; } [12] suspendCaller ( ) // Suspend the caller until the caller is released. while(this.isCallerSuspended()) { this.wait_(); } [13] wait_ ( ) // Wait for an indeterminate amount of time to allow other concurrent // executions to proceed. // [There is no further formal specification for this operation.] 8.4.3.2.3 CallEventOccurrence A call event occurrence represents the occurrence of a call event due to a call to a specific operation. Generalizations *EventOccurrence Attributes None Associations *execution : CallEventExecution The call event execution that created this call event occurrence. Operations [1] getOperation ( ) : Operation // Get the operation being called by this call event occurrence. return this.execution.getOperation(); [2] getParameterValues ( ) : ParameterValue [0..*] // Return the input parameter values from the call event execution for // this call event occurrence, which correspond to the values of the // operation input parameters for the call. return this.execution.getInputParameterValues(); [3] match ( trigger : Trigger ) : Boolean // Match a trigger if it references a call event whose operation is the // operation of this call event occurrence. boolean matches = false; if (trigger.event instanceof CallEvent) { CallEvent callEvent = (CallEvent)trigger.event; matches = callEvent.operation == this.getOperation(); } return matches; [4] returnFromCall ( ) // Release the caller on return from the call. this.execution.releaseCaller(); [5] setOutputParameterValues ( parameterValues : ParameterValue[0..*] ) // Set the output parameter values of the call event execution for // this call event occurrence, which correspond to the values of the // operation output parameters for the call. this.execution.setOutputParameterValues(parameterValues); In 8.6.4.1 Overview, under Accept Event Action, in the first paragraph, replace the last sentence with: In fUML, an accept event action is either a regular accept event action, in which case it can only with for signal events, or it is specialized accept call action, which case it can only wait for call events (see 7.5.4). The discussion on accept event actions below also applies to accept call actions. This is followed by some additional discussion specific to accept call actions. In the third paragraph, in the first sentence, change "a signal event occurrence" to "an event occurrence" and remove "with a signal instance". After the section Accept Event Action and before the section Reduce Action, add the following: Accept Call and Reply Actions An accept call action is a specialized accept event action used to wait for call events. It registers and accepts event occurrences as described for accept event actions in general above. However, when triggered, in addition to producing the unmarshalled values of the input parameters of the called operation (if any), an accept call action produces another output, the return information for the call. Return information is a special value that may be passed on an object flow of an activity, but is only usable as input to a reply action, in order to return from a call. The return information contains a link back to the call event occurrence that triggered the accept call action for the call. When a reply action fires, it takes values for the output parameters of the called operation (if any) from its replyValue input pins and a return information value from its returnInformation pin. It then returns output parameter values to the caller using the reply operation on the return information. This reply operation then sets the output parameter values via the call event occurrence and releases the calling thread, which will have been suspended waiting for a reply to the call (see 8.4.3). Note: A reply action is associated with a trigger that identifies the call event from which the reply actionis returning. The UML Superstructure Specification (subclause 11.3.43) states that "The operation specified by the call event on the trigger must be consistent with the information returned at runtime." In fUML, this is interpreted as meaning that the operation specified by the call event on the trigger must be the same as the operation that was called by the call event occurrence on the return information provided to the call action. If the operations do not match, the reply action has no effect. In Figure 8.35 Accept Action Activations, replace the diagram with: Editorial Note. The above diagram also reflects changes made in the resolution to issue [6]FUML13-25. Under 8.6.4.2 Class Descriptions, add the following subclause, and renumber subsequent subclauses appropriately: 8.6.4.2.1 AcceptCallActionActivation An accept call action activation is a specialized accept event action activation for an accept call action. Generalizations *AcceptEventActionActivation Attributes None Associations None Operations [1] accept ( eventOccurrence : EventOccurrence ) // Accept the given event occurrence, which must be a call event occurrence. // Place return information for the call on the return information // output pin. Then complete the acceptance of the event occurrence // as usual. AcceptCallAction action = (AcceptCallAction) this.node; OutputPin returnInformationPin = action.returnInformation; ReturnInformation returnInformation = new ReturnInformation(); returnInformation.callEventOccurrence = (CallEventOccurrence) eventOccurrence; this.putToken(returnInformationPin, returnInformation); super.accept(eventOccurrence); After 8.6.4.2.6 ReduceActionActivation (8.6.4.2.7 as renumbered), add the following subclauses, and renumber subsequent subclauses appropriately: 8.6.4.2.8 ReplyActionActivation A reply action activation is an action activation for a reply action. Generalizations *ActionActivation Attributes None Associations None Operations [1] doAction ( ) // Reply to the call represented by the return information on // the return information pin using the reply values given // on the reply value pins. ReplyAction action = (ReplyAction) this.node; Trigger replyToCall = action.replyToCall; InputPinList replyValuePins = action.replyValue; InputPin returnInformationPin = action.returnInformation; ValueList values = this.takeTokens(returnInformationPin); ReturnInformation returnInformation = (ReturnInformation) values.getValue(0); if (replyToCall.event instanceof CallEvent & ((CallEvent)replyToCall.event).operation == returnInformation.getOperation()) { ParameterValueList parameterValues = new ParameterValueList(); int i = 1; while (i <= replyValuePins.size()) { ParameterValue parameterValue = new ParameterValue(); parameterValue.values = this.takeTokens(replyValuePins.getValue(i - 1)); parameterValues.addValue(parameterValue); i = i + 1; } returnInformation.reply(parameterValues); } 8.6.4.2.9 ReturnInformation Return information is a value that contains the information necessary to return from an operation call handled as a call event in an activity. It is placed on the returnInformation output pin of an accept call action and is only usable as a value on the input pin of a reply action. Generalization *Value Attributes None Associations *callEventOccurrence : CallEventOccurrence The call event occurrence for the call to which the return information applies. Operations [1] getOperation ( ) : Operation // Return the operation associated with the call event occurrence of this // return information. return this.callEventOccurrence.getOperation(); [2] copy ( ) : Value // Create a new return information value that is a copy of this value, with // the same call event occurrence. ReturnInformation copy = (ReturnInformation)super.copy(); copy.callEventOccurrence = this.callEventOccurrence; return copy; [2] equals(Value otherValue) : Boolean // One return information value equals another if they are for the // same call event occurrence. boolean isEqual = false; if (otherValue instanceof ReturnInformation) { isEqual = ((ReturnInformation)otherValue).callEventOccurrence == this.callEventOccurrence; } return isEqual; [3] getTypes ( ) : Classifier[0..*] // Return information is untyped. return new ClassifierList(); [4] new_ ( ) : Value // Create a new return information value, with an empty call event occurrence. return new ReturnInformation(); [5] reply ( outputParameterValues : ParameterValue[0..*] ) // Reply to the call by setting the output parameters and // releasing the caller. this.callEventOccurrence.setOutputParameterValues(outputParameterValues); this.callEventOccurrence.returnFromCall(); [6] specify ( ) : ValueSpecification // Return information cannot be specified using a value specification. return null; [7] toString ( ) : String // Return a string representation of the return information. String s = "ReturnInformation"; String name = callEventOccurrence.getOperation().name; if (name != null) { s = s + "(" + name + ")"; } return s; ---------------------------------------------------------------------------------------- [1] http://issues.omg.org/browse/FUML13-25 [2] http://issues.omg.org/browse/FUML13-4 [3] http://issues.omg.org/browse/FUML13-1 [4] http://issues.omg.org/browse/FUML13-25 [5] http://issues.omg.org/browse/FUML13-1 [6] http://issues.omg.org/browse/FUML13-25 Actions taken: November 4, 2015: received issue April 6, 2017: Resolved June 22, 2017: closed issue Discussion: End of Annotations:===== m: webmaster@omg.org Date: 04 Nov 2015 01:40:20 -0500 To: Subject: Issue/Bug Report ******************************************************************************* Name: Marc-Florian Wendland Employer: Fraunhofer FOKUS mailFrom: marc-florian.wendland@fokus.fraunhofer.de Terms_Agreement: I agree Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) Section: 7.3.3, 7.5.4 FormalNumber: ptc/2015-09-08 Version: 1.2 Doc_Year: 2015 Doc_Month: September Doc_Day: 01 Page: 48, 82 Title: Introduce CallEvent, AcceptCallAction and ReplyAction to keep consistency with PSSM Nature: Revision Severity: Significant CODE: 3TMw8 B1: Report Issue Remote Name: fokus171193.fokus.fraunhofer.de Remote User: HTTP User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 Time: 01:40 AM Description: fUML shall introduce CallEvent, AcceptCallAction and ReplyAction into fUML and harmonize their semantics with the "fragmented method" paradigm of state machines (and PSSM). In fact, the handling of CallEvents should be the same as the handling of SignalEvents in fUML. This would mean that CallOperationActions do not any longer result in the execution of the method Behavior of an Operation, but in the generation of a CallEvent that is put into the event pool of the target object of the CallOperationAction. This would also require to not permit Operations to contain method - this would be then in synch with Reception. AcceptCallAction should be introduced, or AcceptEventAction should be relaxed to specify Trigger that refer to CallEvents. In addition, ReplyActions shall be included in order to finally send the result of the execution of the Operation.