![]() ![]() |
||||
|
||||
This
section describes some specific issues in the use of PropertyValue objects, particularly in
the use of IntegerValue and RealValue objects.
The
attributes of PropertyValue objects can be changed using the attribute setter methods.
Changing the values of the PropertyValue objects obtained from the property lookup
methods, however, may not have the intended affects on the model. Because the property
lookup methods handle searching the component hierarchies, interpreting references to
property constants, interpreting references to other property values, and evaluating Boolean
expressions, the PropertyValue objects obtained from the lookup may be located in surprising
locations in the model, and it is possible they may be freshly created objects and not located in
the model at all. To change the value of a property it is best to create a new PropertyValue
object to use with setPropertyValue. For example, the following code segment increments
an integer property value associated with a particular component:
final IntegerValue iv = (IntegerValue)
ph.getPropertyValue(pd);
if (iv != null) {
IntegerValue iv2
= PropertyFactory.eINSTANCE.createIntegerValue();
iv2.setNewValue(iv.getValue()
+ 1);
ph.setPropertyValue(pd, iv2);
(We
assume pd refers to a property definition of type aadlinteger.) |
||||
Sometimes
you want to copy a property value from one property association to another. You
might be tempted to use the property value objects returned by a property lookup method and
feed them back to setPropertyValue, as shown below:
// Anti-pattern for copying
property values
final List val = ph.getPropertyValueList(pd_propA);
// Do not do this!
ph.setPropertyValue(pd_propB,
val);
Do
not do this. This can have unexpected effects on the model because it can cause a
PropertyValue object to have a new containing object the meta model, and thus destroy the
original property association. Instead, you should create a copy of the property value objects
and set the new the property value using the copies:
// Pattern for copying property
values
final List val = ph.getPropertyValueList(pd_propA);
// Do this instead
final List valCopy = AadlUtil.copyList(val);
ph.setPropertyValue(pd_propB,
valCopy);
The static
method AadlUtil.copyList(List) takes a List of EObject references and returns a
new List object whose contents are copies of the objects in the original list, in the same order.
Any references shared among the objects in the list are also shared among objects in the
copied list. The copying is performed using the method EcoreUtil.copy(EObject), which
deep-copies an individual model object. These copying methods are useful for copying model
structure generally, but we cover them here because we have found them most useful when
manipulating property values.
Also, IntegerValue
and RealValue (via the superclass NumberValue) contain the methods
cloneNumber() and cloneAndInvert(). The first method returns a copy of the number.
The
second returns a copy that has the inverse value. |
||||
To
get the string representation of a property value, use the method
PropertyValue.getValueAsString(). |
||||
The
AADL specification allows the minimum, maximum, and delta components of the range to
be specified using either literals or references to property constants. Thus, in the meta model,
the minimum, maximum, and delta attributes of RangeValue
contain
NumberOrPropertyReference objects. You can get the value of a
NumberOrPropertyReference object using getNumberValue(). We have added three
convenience methods to RangeValue to provide direct access to the numeric values of its
attributes: getMinimumValue(), getMaximumValue(), and getDeltaValue(). All
three
methods return a NumberValue. |
||||
Given
a UnitsType object, the member UnitLiteral objects can be retrieved by name using
the method UnitsType.findUnitLiteral(String unitName). If no literal with the given name
exists the method returns null.
Similarly,
the method EnumType.findEnumLiteral(String litName) looks for the named
enumeration literal in the given enumeration type, and returns null if the literal is not found. |
||||
As
described in Section 5.2.1 AADL Property Types, aadlreal and aadlinteger property
types can specify that their values have units. In the meta model, this is captured by the
unitLiteral attribute of NumberValue. However, the value attribute
of RealValue and
IntegerValue is maintained separately from unitLiteral. It is thus the case
that interpreting
the actual value represented by a RealValue or IntegerValue involves checking the values
of
two attributes, as well as interpreting the value of the unit literal itself relative to the other unit
literals in its UnitType.
OSATE
shields the plug-in programmer from this tedious process via the methods
NumberValue.getScaledValue() and NumberValue.getScaledValue(UnitLiteral). Both
methods return a double value: the first returns the value scaled relative to the base unit of
the
numbers UnitsType; the second method returns the value scaled relative to the given
UnitLiteral, which must be from the numbers UnitsType.
For
example, consider the IntegerValue representing the AADL property expression 30 foot
of type Example::Length. Method getScaledValue()
returns 360.0, the value scaled to the
base unit inch. Invoking the parameterized
method with the UnitLiteral object representing
the unit yard returns 10.0.
Thus, given a PropertyHolder object ph representing a
component whose Example::Documentation_Thickness property has value 30 foot,
executing the following segment of code
final UnitsType units =
(UnitsType) OsateResourceManager.findPropertyType(
"Example", "English_Units");
final IntegerValue iv =
(IntegerValue) ph.getSimplePropertyValue(
"Example", "Documentation_Thickness");
System.out.println("Scaled
Value: " + iv.getScaledValue());
System.out.println("In
Yards: " +
iv.getScaledValue(units.findUnitLiteral("yard")));
results
in the following console output:
Scaled Value: 360.0
In Yards: 10.0 |
||||
The
class NumberValue contains the attribute valueString which shadows the value of the
value attribute of RealValue and IntegerValue. This attribute is maintained
so that the
number value can be unparsed to the same syntactic form from which it was parsed. This is
important because AADL allows integer values to be denoted in bases other than ten, allows
exponential notation for real values, and allows underscores to be inserted between numerals.
These syntactic features are often important to the readability of specifications, and thus it is
separately maintained in the valueString attribute.
As
a consequence, when the value attribute of a NumberValue is changed, the valueString
attribute should also be. Because it is inconvenient, and error prone, to expect that
setValueString be invoked every time setValue is invoked, NumberValue also features
the
method setNewValue(Number) which simultaneously updates both the value and
valueString attributes. Class RealValue has the more specific method
setNewValue(double), and class IntegerValue has the more specific method
setNewValue(long). Because integer values may be denoted in bases other than ten,
IntegerValue also has the method setNewValue(long value, int base), which allows the
base that the string representation should be in to be specified. If the base is not a value
between two and sixteen inclusive, base ten is used.
We
do not offer any methods for controlling how a real value is represented as a string; the
setValueString method can be used in conjunction with the java.text.DecimalFormat class
to exercise finer control over the unparsing of RealValue objects.
The
unit literal for a number value, if one is desired, is set by the setUnitLiteral method.
As
an example, executing the code segment
final UnitsType units =
(UnitsType) OsateResourceManager.findPropertyType(
"Example", "English_Units");
final IntegerValue iv2 =
PropertyFactory.eINSTANCE.createIntegerValue();
iv2.setNewValue(18L);
iv2.setUnitLiteral(units.findUnitLiteral("inch"));
System.out.println("New
value: " + iv2.getValueAsString());
System.out.println("valueString:
" + iv2.getValueString());
System.out.println("Scaled
Value: " + iv2.getScaledValue());
System.out.println("In
Feet: " +
iv2.getScaledValue(units.findUnitLiteral("foot")));
results
in the following console output.
New value: 18 inch
valueString: 18
Scaled Value: 18.0
In Feet: 1.5 |
||||