Selector
Product line architectures (PLAs) are used to describe a family of closely related products. A PLA describes a set of common core components as well as the variation points across the specific product architectures. The variation points modeled by xADL 2.0 are optional elements and variant types (in the Options and Variants schemas).
Optional elements may or may not be included in the selected product architecture and a variant type will always
be included, but may take on different alternative forms for different product architectures. Optionality is specified
by a boolean guard (if the guard condition is met, the element is included) and variants are specified
by mutually exclusive boolean guards (the variant whose guard condition is met is selected).
The selector component is able to automatically select a product architecture (or a smaller PLA) from
a PLA based on user specified constraints. These constraints are simply name-value pairs in a
symbol table.
The selector will remove any optional element whose guard
conditions are not met, or remove the optional tag (which includes the guard) if its conditions
are met (thus making it mandantory).
For example, an optional component before selection might look like this.
Here is Comp2 shown with its optional field which contains the boolean guard: x @[0, 50] || y > 0
(Note: x@[0, 50]
is the notation for in range, i.e. 0 <= x <= 50
).
That same component in abbreviated non-XML notation looks like this:
component{ (attr) id = "Comp2" //Description and other properties elided for //simplicity optional{ guard{ booleanExp{ or{ booleanExp1{ inRange{ symbol = x value = 0 value = 50 } } booleanExp2{ greaterThan{ symbol = y value = 0 } } } } } } (xlink) type = "#Type_1" } |
If the guard condition is met, its optional field is removed. So for our example
if in the symbol table we define x = 10
(regardless of what y is deinfed as),
after selection the optional component will look like this:
And now, that same component in abbreviated non-XML notation will look like this:
component{ (attr) id = "Comp2" (xlink) type = "#Type_1" } |
Please note that optional field has been removed; this component is now part of the architecture. However, if the guard were evaluated to false, the component would be removed from the architecture. If parts of the guard could not be evaluated, the boolean expression will be simplified as much as possible. And the new boolean guard will only be the conditions that were not specified.
The selector will also select the appropriate variant type. Each variant type contains a number of variants, each one with its own guard condition and a type. The guard conditions for the set of variants in a variant type are assumed to be mutually exclusive. The selector evaluates the guard condition for each variant. If a guard condition evaluated to 'false,' the variant is removed from the type. If one of the guards evaluates to 'true,' all elements (components, connectors, etc.) of the variant type will have their types changed to that of the the selected variant. If guards could not be fully evaluated, those guards will be pared down with available information and no types of elements (components, connectors) will be changed.
Here is a variant component type (Type_1) with two variants (two possible types: 1.1 and 1.2):
Which would translate to the following in abbreviated non-XML notation:
componentType{ (attr) id = "Type_1" variant{ guard{ booleanExp{ equals{ symbol = language value = "English" } } } (xlink) variantType = "#Type_1.1" } variant{ guard{ booleanExp{ equals{ symbol = language value = "Spanish" } } } (xlink) variantType = "#Type_1.2" } } |
The first variant has the guard language == "English"
and the second variant
has the guard language == "Spanish"
. If we perform selection based on a symbol table with
the entry language = "English"
, variant Type_1 will then look like this:
Translated to abbreviated non-XML notation, this is:
componentType{ (attr) id = "Type_1" variant{ guard{ booleanExp{ bool = true } } (xlink) variantType = "#Type_1.1" } } |
Note that the variant pointing to Type_1.2 is removed because its guard evaluated to false, but the
Type_1.2 remains in the document. Also, the guard for variant representing Type_1.1 has been reduced
to a single boolean expression containing the boolean value 'true'
.
As noted above, the selection algorithm will also go through all the components that were originally
of component type Type_1 and update them so that those components will now be of type Type_1.1.
Note that the algorithm will report an error if all of the guards for the variants (of a single variant component type) evaluate to false or if more than one guard evaluates to true.
The selector requires the Boolean Eval component to evaluate
the boolean guards used in optional and variant elements. Please see the options and variants schema
in xADL 2.0 for a list of optional and variant
elements that are supported by the selector.
The selector component is an asynchronous component and communicates through the following messages:
To invoke the selection service, the requesting component must send the PerformArchSelectorMessage
.
PerformArchSelectorMessagepublic PerformArchSelectorMessage(String archURL, String targetArchURL, String componentID, SymbolTable table, String startingID, boolean isStructural)
|
The symbol table can be created from a file with the following format: The file must be in ASCII. Comments can be represented by // just as in C++ or Java. The basic layout of the file is as follows:
Variable = value Variable = value etc.
There can be leading and trailing spaces that will be stripped away. The value of the variable is represented by strings as specified here. Some examples:
/* Set the value of alarm variable to the date Jan 1st 2003 */ alarm = #1/1/03# /* Set the value of speed variable to the number 23.1 */ speed = 23.1 /* Sets the value of language variable to the string 'English' */ language = "English"
Then, to invoke the selector:
/* In a C2Component*/ // Imports import archstudio.comp.selectordriver.FileParser; ... // First create the symbol table from file FileParser parser = new FileParser( ); SymbolTable myTable = parser.createTable( "myTable.txt" ); // Then create the message // This invokes the selection on the architecture at archURL, // with the starting point specified by startingID, which // refers to an arch structure element PerformArchSelectorMessage selectMessage = new PerformArchSelectorMessage(archURL, targetURL, id, myTable, startingID, true); // Sends the request upwards sendToAll(selectMessage, topIface); |
During the selection process, the selector will continuously send out messages to inform other components of its progress:
ArchSelectorStatusMessagepublic ArchSelectorStatusMessage(String selectedArchURL, String componentID, int currentValue, int upperBound ,boolean isDone, boolean errorOccurred, Exception error)
|
Additional questions about the Selector should be sent to Ping H. Chen.