Properties and Operations
This page describes the following topics related to implementing delegate classes for blocks:
- Mapping block properties into Java field types
- Naming Java methods that implement block operations
- Wiring up instance specification slot values to their Java fields
Java field types
Properties in blocks map to special fields in java delegates of type com.agi.moxie.api.models.Property
.
This type and its implementations support change tracking of property values during simulation.
Do not use the assignment operator to assign a value to a Property
instance in a delegate or opaque expression.
Instead, use the Property
methods to get and set its value. Alternatively, you can add your own getters and setters
to ensure you do not interfere with the mechanics of state changes.
Type | Description |
---|---|
Property
|
Represents a block's property. This is an abstract class that the following types extend. |
BasicProperty
|
Represents the most basic implementation of a simple mutable Property .
|
ConstantProperty
|
Represents a simple property that contains a single compile-time constant that never changes and, as such, cannot accept any assignment. This provides a simple way to specify a value in Java that may not exist in an instance specification slot. However, if you provide an instance specification slot, the wire-up process will set the value from it instead. |
DerivedProperty
|
Represents a property in which its underlying value is computed on-demand either from the values of other properties or as the result of performing some analysis with a separate tool. |
ListProperty
|
Represents a property where the multiplicity of the corresponding SysML property is greater than 1. Its underlying type is a Java
List .
|
For more information on Property
types, see the
com.agi.moxie.api.models.Property API
documentation.
Primitives
Properties that contain primitive values in the SysML will be represented in Java with their corresponding primitives in Java. Accessing and setting their values in the SysML will track any updates and reflect those changes in change events and guards.
SysML Type | Java Type |
---|---|
SysML::Libraries::PrimitiveValueTypes::Boolean
|
java.lang.Boolean
|
SysML::Libraries::PrimitiveValueTypes::Integer
|
java.lang.Integer
|
SysML::Libraries::PrimitiveValueTypes::Real
|
java.lang.Double
|
SysML::Libraries::PrimitiveValueTypes::String
|
java.lang.String
|
UML Standard Profile::MagicDraw Profile::datatypes::boolean
|
java.lang.Boolean
|
UML Standard Profile::MagicDraw Profile::datatypes::double
|
java.lang.Double
|
UML Standard Profile::MagicDraw Profile::datatypes::int
|
java.lang.Integer
|
Units
Behavior Execution Engine
supports ingesting numeric quantities with associated units from SysML and makes
use of the third party "Units of Measurement" (UOM) API from
JSR-385.
For details, see their API documentation and samples for the usage of the javax.measure.Quantity<T>
and javax.measure.Unit<T>
types that enable you to represent and convert between quantities.
Whenever a SysML block contains a value property with a value type that has both a Quantity Kind
and a Unit
, the type of that property is
represented in Java as Quantity<*>
. Alternately, if you know the kind of Dimension
you want, you can specify
the specific quantity type. For instance, for a unit of meters, you can use Quantity<Length>
. The
Dimension
type in the UOM library is not one-to-one with the quantity kinds available in the ISO-80000 specification
in
SysML. AGI has mapped the quantity kind of the SysML value types to the appropriate Dimension
type in UOM. While
this limits some of
the type safety available in Java, it still enables you to accept and convert between the units specified in the SysML with a standard Java
library. Furthermore, the delegate module descriptor allows you to register custom units with the engine
to support any units that aren't automatically mapped from ISO-80000-3.
To support conversion between units,
Behavior Execution Engine
provides the MoxieUnitConverter, which you can request using the
@InjectByName("moxieUnitConverter")
injection parameter. This allows you to convert from
one type of javax.measure.Quantity<?>
to another as well as create new instances of quantities with
appropriate units.
Multiplicity
Block properties with a multiplicity greater than one correspond to ListProperty
in Java. This
is a special kind of Property
that exposes list-like operations directly to the expression language. Rather than
having to
unwrap the Property
to get a List
, the ListProperty
enables you to add, remove, or modify the contents
of the SysML property in a stateful manner. Changes in the contents of the property will be reflected in the engine during execution.
Look at the following Java example in Figure 1, which has a block property named
passengers
of type Passenger
with a multiplicity of 0..*
:
public ListProperty<Passenger> passengersProperty() {
return mPassengers;
}
Figure 1: A passengers property with a multiplicity of 0..*
Naming
When implementing a block operation as a Java method, ensure that:
- The name of the Java method is identical to the block operation in spelling and case.
-
The return type matches the corresponding type with the
@DelegateFor
annotation.
For a Block Operation Named... | ...use this Java Method |
---|---|
turnBurnerOn
|
turnBurnerOn()
|
TurnBurnerOn
|
TurnBurnerOn()
|
For operations, the casing of the corresponding method matches the block. The same is true for properties except that the method must end with "Property". Otherwise, the casing is the same. This may cause some inconsistency with Java style guides. However, consistency with the SysML model takes precedence.
Also, SysML allows for special characters that are illegal for Java feature names. Spaces and reserved operator characters are not allowed. Any such characters must be replaced with an underscore in the Java method name. Here are some examples:
For a Block Property Named... | ...this is the Java Property method |
---|---|
maxFlightDuration
|
maxFlightDurationProperty()
|
SomeWeIrDlyCASEDValue
|
SomeWeIrDlyCASEDValueProperty()
|
sp#c!@l ch^r^ct&r$
|
sp_c__l_ch_r_ct_r$Property()
|
Wire-Up
For every property with a slot value specified in an instance, the
Behavior Execution Engine
attempts to "wire up" the property values.
For example, if a model property is named someSetting
, the engine expects to see a Property
method named
someSettingProperty
in the Java delegate. The initialization step will then assign the slot value to that property
after
instantiating the Java object but before starting the simulation.
Whether or not that parameter shows up as @InjectBySlot
in the constructor, any values provided in the slots
of the instance
will be assigned to properties within the delegate. This occurs after calling the constructor and is guaranteed to happen prior to the
start of the simulation. Any (default) values you assign in your constructor will be overwritten unless a slot value is not provided in SysML.
The instances are not created in a particular order. So, before simulation start, values may not be assigned to their respective properties
until all objects are created. In Figure 2, the currentVehicle
is not
specified in the constructor. The value of this currentVehicle
property will default to null,
but because it is specified in the instance specification for the simulation,
the wire-up process will initialize the value prior to simulation start.
The wire-up process can also be useful in cases where there are circular dependencies between types. Since you cannot create two objects simultaneously in Java, two objects that reference each other cannot be constructed simultaneously. Instead, by removing the constructor parameters, wire-up will handle assigning the objects correctly. Once all objects are created, the instance of each dependency will be assigned to the appropriate property on the other object prior to simulation start.
public AdultPassenger(
@InjectByName("instanceName") String instanceName,
@InjectByName("timeProvider") TimeProvider timeProvider) {
mInstanceName = instanceName;
// The following value will be initialized at runtime from the instance specification using property wire-up
mCurrentVehicle = new BasicProperty<>(timeProvider, null);
}
Figure 2: An example wire-up