Delegate Classes
There are many different ways to create a delegate, depending on the level of custom functionality you want to implement. In fact, if you do not provide any code at all, Moxie will attempt to implement the following behaviors for you when you run your simulation:
- Java
Property
methods to represent the state of SysML object properties in the simulation - Assignments for slot values provided in an Instance Specification by using wire-up initialization
- Implementations for operations that do not perform actions and return default values
- Support for call events resulting from executing operations
If this is good enough for your simulation, you do not need to write a single delegate. As a matter of fact, you do not even need a delegate module. Moxie will handle everything for you as is, right out of the box. Please see Auto-Implementation to learn more.
If you are using an analysis tool, you will want to create some custom delegates to interact with it. You can do as much or as little as you need, and Moxie will attempt to fill in the gaps for you with appropriate defaults.
To get started writing a delegate, the first thing you need to do is create a Java class or interface to represent the block that owns the properties and operations to be implemented. Often, creating interfaces that represent only the elements that exist in the SysML block can be useful to maintain the abstraction between the formal model and the code executing it. An interface also helps cases where there is more than one implementation for a particular block. Different implementations may be used and maintained for different simulations or analysis tools.
Let's take a look at Figure 1 and Figure 2, which show the properties and operations of the balloon operator from the hot air balloon ride example.
Figure 1: The balloon operator properties
Figure 2: The balloon operator operations
The names of the properties and operations contained in the interface or class for your delegate must align with those in the corresponding block. Fortunately, you do not have to do this by hand. Moxie provides a utility to generate interfaces and classes for you that you will simply need to implement. See Delegate Code Generation .
Figure 3 shows the interface representing BalloonOperator
.
package com.agi.moxie.samples.balloonride.structure;
import com.agi.moxie.api.annotations.DelegateFor;
import com.agi.moxie.api.models.Property;
import com.agi.moxie.delegates.base.FixedDuration;
import com.agi.moxie.delegates.base.Thing;
import com.agi.moxie.delegates.core.FixedScalarValue;
import java.lang.Boolean;
@DelegateFor("Structure::BalloonOperator")
public interface BalloonOperator extends Thing {
Property<FixedDuration> maxFlightDurationProperty();
Property<FixedScalarValue> targetAltitudeProperty();
Property<FixedScalarValue> launchPadAltitudeProperty();
Property<Boolean> isOperatingProperty();
Property<Passenger> passengerProperty();
Property<Balloon> balloonProperty();
void sendLandedSignal();
Passenger getNextPassenger();
void launch();
void land();
void sendBuckleUpSignal(Passenger target);
void sendReadyForPhotoSignal(Passenger target);
}
Figure 3: The balloon operator delegate interface
In Figure 3, take note of the @DelegateFor
annotation on the interface. There you will see the
qualified name of the block represented by this interface. Next, you will notice the interface extends Thing
, which
corresponds to the block's
generalization of Moxie-Base::Structure::Thing
from
the Moxie model libraries.
Finally, take a look at the Java methods and compare them to the properties and operations in Figure 1 and
Figure 2. You will notice that all of the SysML properties are represented in Java with their
name followed by "Property" as a convention to indicate they represent a model property. Aside from the "Property" suffix, the
properties in the interface are spelled exactly the same as they are in the block. However, if there are any characters that
are illegal for Java identifiers, they will be replaced with an underscore. Operations do not have a prefix or suffix, and their
spelling and casing in the interface are identical to the block.
For more details on properties and operations, see Properties and Operations.
Now let's look at the implementation of the BalloonOperator
interface in Figure 4, namely BalloonOperatorDelegate
.
package com.agi.moxie.samples.balloonride.structure.impl;
import com.agi.moxie.api.StateMachineRemoteControl;
import com.agi.moxie.api.annotations.AutoDelegateImplementation;
import com.agi.moxie.api.annotations.DefaultDelegate;
import com.agi.moxie.api.annotations.InjectByName;
import com.agi.moxie.samples.balloonride.structure.BalloonOperator;
import com.agi.moxie.samples.balloonride.structure.Passenger;
@AutoDelegateImplementation
@DefaultDelegate
public abstract class BalloonOperatorDelegate implements BalloonOperator {
private final StateMachineRemoteControl mStateMachineRemoteControl;
public BalloonOperatorDelegate(@InjectByName("stateMachineRemoteControl") StateMachineRemoteControl stateMachineRemoteControl) {
mStateMachineRemoteControl = stateMachineRemoteControl;
}
@Override
public void sendLandedSignal() {
this.land();
mStateMachineRemoteControl.sendSignalEventToSelf("Structure::BalloonOperator::Landed");
}
@Override
public void sendReadyForPhotoSignal(Passenger target) {
mStateMachineRemoteControl.sendSignalEvent("Structure::Passenger::ReadyForPhoto", target);
}
@Override
public void sendBuckleUpSignal(Passenger target) {
mStateMachineRemoteControl.sendSignalEvent("Structure::Passenger::BuckleUp", target);
}
}
Figure 4: The balloon operator delegate class
As you can see in Figure 4 above, a Java delegate class contains several key components:
- Java Annotations - These provide
Moxie
with instructions on how to instantiate and configure simulation runtime instances.
If the class does not include the
@DelegateFor
annotation, it should at least implement an interface or another base class that does. - Injection constructor - This is the constructor on a Java delegate. The injection constructor is responsible for injecting instance specification slot values and runtime dependencies into a delegate runtime instance's private fields.
- Java
Property
methods - These correspond to block properties. - Java methods - These correspond to block operations.
See the following topics for more detail about these components: