An important aspect of the ControlTier model schema are constraints. Constraints let you define rules that govern how instances are created and edited. For example, you can define a set of allowable literal values for a given type property. You can make one of these allowed values the default one. You can even enforce that only one of the allowable values can be selected.
You can also use constraints to govern how Objects are composed together into your model. For example you can restrict a Type to only allow Objects of another specific type as its child dependencies, or its parent dependencies.
Using constraints allows you to define how things fit together in your object model, and what values you can use in properties.
The ControlTier Type modeling system provides a class-based object-oriented design system.
Each type in the system has a set of pre-defined Properties. (See Type modeling).
Objects of each type can have a custom value set for those properties. Properties are either of type "string", or of type "instance". A string property accepts a string value, and an instance property accepts another Object as a value (or a set of Objects).
To see the Constraints for a Type, click the "Constraints" tab when in the Type View page:
The "Property Value Constraints" column shows the constraints set for each Property. Most constraints are labelled with the name of the type of constraint, and the value that is set for that type of constraint.
- Note: Inherited constraints are shown with the constraint type in italics. These constraints cannot be removed, however they can be overridden by setting a different value.
To set or change a constraint on a property, navigate to the Constraints tab of the Type, and click the Pencil icon to edit the constraint for a particular Property.
Once you have clicked the Edit (pencil) icon for a String Property, you will see the Edit String Constraint form:
Each String Property can have the following constraints applied to it:
- Default Values
- A set of literal values which can be selected by the user when modifying this property of an object. (labelled as "default-values")
- Single Default Value
- A single literal value selected from the Default Values list which is the initial default value for the property. (labelled as "default-value")
- Enforce from Default Values
- An option to require that only values from the list of Default Values are accepted for this property.
Add a String Constraint
To Add a new Default Value to the list, enter it in the "New Value" field and click the "Save" button:
The property list will now show the value you added:
Set the Single Default Value
To set the Single Default Value, click the Pencil icon again.
In the form, click the radio button in the "Default" column, to select the value that will be the Single Default Value. In this example we have added a few more Default Values, and have selected the second one as the Single Default Value:
Set Enforce from Default Values
To change whether the constraint is Enforced from Default Values, choose "Yes" or "No" under the "Enforce from Default Values":
Remove a Default Value
To remove a single string from the Default Values set, first click the Pencil icon to edit the constraint.
In the form, deselect the checkbox in the left-hand "Include" column, for the string you wish to remove.
Then click the "Save" button.
To remove all constraints, see #Removing All Constraints for a Property.
String constraints inside type.xml
For a full reference about the syntax used here, see Type-v10.xml#constraints.
In type.xml, add an
<allowedvalue-constraint> element inside the
<constraints> element. Set the "type-property" constraint to the Property Name, in this example, the "deployment-basedir" property:
<allowedvalue-constraint type-property="deployment-basedir"> </allowedvalue-constraint>
To set the Enforce from Default Values constraint, set the
enforced attribute to "true" or "false":
<allowedvalue-constraint enforced="true" type-property="deployment-basedir"> </allowedvalue-constraint>
<allowed-value> element to indicate a Default Value. Set the "value" attribute to the value you want, and the "default" attribute to either "true" or "false". If set to "true", then this value is the Single Default Value:
<allowedvalue-constraint enforced="true" type-property="deployment-basedir"> <allowedvalue value="/home/ctier/myservice" default="false"/> <allowedvalue value="/opt/service/myservice" default="true"/> <allowedvalue value="/usr/local/myservice" default="false"/> </allowedvalue-constraint>
String Constraint in Action
To see how the String Constraints work, create a new Object of the Type, or edit an existing Object.
You will see that the text field for the Property you have set a String Constraint on will now have a pop-up menu next to it to let you select from the Default Values. If you have a Single Default Value set, then that value will appear in the text field automatically. In this example, the Enforce Default Values constraint is set to false:
If you set the Enforce Default Values constraint to
true, then the form will no longer include a text field and will only show the pop-up menu of Default Values:
Only two properties are Instance-type Properties:
- referrers - i.e. Parent dependencies
- resources - i.e. Child dependencies
(Note: only Types that are a subtype of the Assembly Type have the "resources" property. This does not include Setting, for example.)
Each of the Instance Properties can have constraints applied to it for the Type.
Typically, a new subtype will have a set of Inherited Constraints that are inherited from the supertype for these two properties. If you decide to override these constraints, be sure to analyze the inherited ones first to see if you need to retain any of them.
Both of the Instance Properties can have these constraints applied to it:
- Allowed Types
- This is a set of Types, indicating that only Objects of one of these Types are allowed as values of this property. (labelled as "allowed-types".)
- Singleton Types
- This is a subset of the Allowed Types, that indicates that only a single Object of the specified type is allowed as a value of this property. (labelled in the GUI with the Singleton Icon.)
- Default Objects
- This is a set of Objects (all of which must have a class of one of the Allowed Types), which are used as default values for the property, when a new Object of the current Type is created. (labelled as "default-instances".)
Combining Instance Constraints
The Allowed Types and Singleton Allowed Types constraints for the 'resources' and 'referrers' properties will affect each other when you are selecting dependencies for an Object.
An Object 'a' of Type A can have another object 'b' of Type B as a child dependency if and only if:
- A has an Allowed Type constraint for its 'resources' property that includes B or a supertype of B.
- AND, if B is a Singleton Allowed Type, then 'a' doesn't have an Object of type B as a child dependency already
- AND B has an Allowed Type constraint for its 'referrers' property that includes A or a supertype of A.
- AND, if A is a Singleton Allowed Type, then 'b' doesn't have an Object of type A as a parent dependency already
In this diagram, black arrows indicate Allowed Types for resources or referrers, and gray arrows indicate inherited or implied Allowed Types constraints. The green arrow indicates subtyping:
Only where there are arrows in both directions in the above diagram are Dependencies allowed.
Objects thus would be allowed to have dependencies as indicated in this diagram, with blue arrows indicating allowed child/resource dependencies, and red arrows indicating disallowed dependencies:
Edit Instance Constraints
Click on the Pencil icon next to the Instance Property to edit the constraints, and you will see the Edit Type Constraint form:
Add an Allowed Type Constraint
In the Edit Type Constraint form, click the "+" icon next to the "Allowed Types" text:
You will then see a list of all Types defined in the Project. For your information, those Types that were already set as Allowed Types are highlighted in yellow.
Select any type by checking the checkbox on the left-hand side of the table.
Then click the Save button.
You will see the list of Instance Constraints in the Constraints list:
The Singleton Icon indicates which Allowed Types are also Singleton Allowed Types.
Add a Singleton Allowed Type Constraint
In the Edit Type Constraint form, either choose from the existing set of Allowed Types, or use the Add Allowed Types button to show all Types in the system. In the list, check the right-hand side checkbox to indicated that the selected Type is a Singleton Allowed Type:
Remove an Allowed Type Constraint
In the Edit Type Constraint form, uncheck the left-side checkbox for the Allowed Type you wish to remove, and click the "Save" button.
Remove a Singleton Allowed Type Constraint
In the Edit Type Constraint form, uncheck the right-side checkbox for the Singleton Allowed Type you wish to remove, and click the "Save" button.
Add a Default Object Constraint
- NOTE: Default Object Constraints currently only work for the
In the Edit Type Constraint form, click the "+" icon next to the "Default Objects" text:
You will then see a list of all Objects of the Allowed Types, and you can select any object by checking the checkbox on the left-hand side of the table. For your information, those Objects that were already set as Default Objects are highlighted in yellow.
Notice that any Objects of the Singleton Allowed Types are listed using a radio-button rather than a checkbox. This allows you to only select a single object of that type.
Click the "Save" button.
Instance constraints inside type.xml
For a full reference about the syntax used here, see Type-v10.xml#constraints.
In type.xml, add an
<dependency-constraint> element inside the
Set the "kind" attribute to indicate the property. Set it to "parent" to indicate the "referrers" property, and set it to "child" to indicate the "resources" property.
<dependency-constraint kind="child" > </dependency-constraint>
To add Allowed Types to the dependency-constraint, add a
<allowedtypes> element, and one
<typereference> for each Allowed Type:
<dependency-constraint kind="child" > <allowedtypes> <typereference name="MyPortSetting" /> </allowedtypes> </dependency-constraint>
To add Singleton Allowed Types to the dependency-constraint, add a
<singletontypes> element, and one
<typereference> for each Singleton Allowed Type:
<dependency-constraint kind="child" > <allowedtypes> <typereference name="MyPortSetting" /> </allowedtypes> <singletontypes> <typereference name="MyPortSetting"/> </singletontypes> </dependency-constraint>
- Note: any types added as Singleton Allowed Types are implicitly added as Allowed Types as well.
Instance Constraints in Action
Setting the Allowed Types for the resources property will restrict the set of possible objects when you edit the Children of an Object.
In the view page for an Object of your Type, expand the "Child Dependencies" section, and click the "change..." or "add.." button:
In the Form titled "Modify This Object's Child Dependencies", you will only see Objects of the Allowed Types in the form. Additionally, Objects of the Singleton Allowed Types will appear with radio buttons rather than checkboxes, allowing you to only select a single Object of those Types:
If you have set the Default Objects for the
resources property, you will see the Default Objects shown as resources in the Create Object form:
Constraints can be inherited from a supertype. This means that a new subtype automatically acts with the same constraints as the supertype.
Please note these characteristics of the way that Inherited Constraints work:
- Constraints are inherited independently for each Property.
- This means that you can selectively override the constraints for one property, and still use the inherited constraints for another.
- Constraints for a Property are inherited completely or not at all.
- This means that you cannot "merge" custom constraints, for example Default Values or Allowed Types, with the inherited constraints. If you modify the constraint for a Property at all, then the inherited constraints are not used.
- Note: the Workbench GUI aids you a bit, by essentially copying the constraints of the supertype if you edit them, giving you the set of Inherited Constraints to start with.
- However, if you set constraints in a type.xml file, those constraints will mask out any Inherited Constraints completely, unless you duplicate the XML constraints defined in the supertype's type.xml file.
Removing All Constraints for a Property
To remove all existing Constraints for a property, click the "x" icon and click the "Yes" button to remove the constraint.
- Note: Constraints that are inherited cannot be removed. See #Inherited Constraints