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 properties in 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

Moxie 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, Moxie 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:

  1. The name of the Java method is identical to the block operation in spelling and case.
  2. 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 Moxie 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