Structure Engine

One of the core tasks of [fleXive] is to store and query data. Like in relational databases or well-formed XML files, data needs to match a predefined structure. When [fleXive] was designed the requirements were as follows:

A good analogy to explain how structures in [fleXive] are organised are classes and object instances: a class in an object oriented programming language describes which attributes (in [fleXive] called properties) are available. If an attribute itself acts like a container for other attributes we call it a group. We call the class analogon Type (implemented in the class FxType), attributes property (implemented in FxProperty) and a collection of attributes Group (implemented in FxGroup).

To enable reuse of properties and groups these entities are independent of types and need to be assigned to types (and respectively groups). The benefit of this system - although it might sound a bit confusing at first glance - is that different types and assignments can share the same property which can be a big advantage for query operations [1] .

A special extension to types are relations (implemented in FxType, mode: Relation) which mimics the behaviour of attributed n:m relations known from SQL.

Structure elements can be addressed using XPath-like expressions as shown in the section called “Content Engine”.

Table 6.2. [fleXive] structure elements
Element Class Description
Type FxType A type, identified by its name, defines behaviour (what kind of permissions may be applied, storage model or language mode is to be used, etc.) and structure (properties and groups are assigned to types).
Relation FxType (mode:Relation) A relation is basically a type that relates (or links) two other types together. A good analogy is an attributed relation known from SQL. It is possible to define how many times a specific instance may be used as a relation source or destination and which types may be related.
Property FxProperty A property defines a name and a datatype (and some options). Thats all there is to it! It can only exist (and is of relevance) if it is assigned to a type or group. The purpose of keeping properties and their assignments separate is the ability to share them and query across multiple types with a single property.
Group FxGroup A group serves as a container for properties and combines them to an entity. Groups - just like properties can not exist without assignments to types ( FxGroupAssignment). The purpose for their existance is like for properties: the ability to share and query across multiple types.
Assignment FxAssignment An assignment is the correlation of groups and properties to types. A group or property can only be used in instances if it is connected to a group assignment or a type.
Property assignment FxPropertyAssignment The assignment of a property to a group assignment or a type. If the property that is being assigned permits, settings like the access control list or options may be overridden.
Group assignment FxGroupAssignment The assignment of a group to a group assignment or a type. If the group that is being assigned permits, settings like the access control list or options may be overridden.

Following the convention on how to update or create new instances of classes in [fleXive], for every class exists (or should exist ;-) ) an editable class. These editable classes can either be instantiated with ClassName.createNew(..) or classInstance.asEditable() depending on if you want to create a new instance or edit an existing.

A type, identified by its name, defines behaviour (what kind of permissions may be applied, storage model or language mode is to be used, etc.) and structure (properties and groups are assigned to types).

The following is a list of parameters that can be passed as arguments to FxTypeEdit when editing or creating a new type:

Table 6.3. FxTypeEdit parameters
Parameter Method Create Edit Description
ACL setACL(ACL acl) X X The ACL which is checked when new instances of this type are created. Will only be checked if the type is configured to check permissions.
Default instance ACL setDefaultInstanceACL(ACL defaultInstanceACL) X X Sets the default instance ACL which is assigned to newly created content instances of that type per default.
Category setCategory(TypeCategory category) X X A type can be assigned the categories User orSystem. A User categorized type can be edited by anyone with proper roles (StructureManagement), whereas System categorized types are ment to be [fleXive] internal and only to be changed by users with the role GlobalSupervisor. The mode may only be changed by users with the role GlobalSupervisor (under ordinary circumstances changing the category of a type should never be necessary).
Check validity setCheckValidity(boolean checkValidity) X X If set totrue, content instances can be assigned a validFrom and validUntil Date. FxContent instances provide anisValid(long time)-Method to check if they are valid at the requested time. This feature is particularly useful in queries since only valid content instances will be returned. Using this feature allows for instance time triggered publication (and removal) of articles.
Label setLabel(String label) X X Set a label for the type. Of relevance only to user interfaces.
Enable parent assignments setEnableParentAssignments(boolean enableParentAssignments) X - If a type is derived from another type, this flag decides if the derived assignments should be enabled. This is by default enabled when creating a derived type: FxTypeEdit.createNew(String name, FxString label, ACL acl, FxType parent) and can be disabled using this method before the derived type is saved.
History age setHistoryAge(long historyAge) X X If trackHistory is enabled for this type, the historyAge determines the duration for which history entries exist. All entries older than this time (in milliseconds) will be removed. History entries are changes to the type or instances and are not fully implemented yet.
Language mode setLanguage(LanguageMode language) X (X) Set one of the supported language modes:
  • None: Content is not language dependent
  • Single: One language per content may be defined
  • Multiple: Every property may exist in different languages
The language mode of existing types can only be changed if no content instances exist.
Maximum destination count (Relation) setMaxRelDestination(int maxRelDestination) (X) (X) Restrict the total number of instances that may be related to a source instance using this relation type. The value 0 means unlimited. This value can only be set if the type is a relation and no instances would invalidate this restriction.
Maximum source count (Relation) setMaxRelSource(int maxRelSource) (X) (X) Restrict the total number of instances that may be related to a destination instance using this relation type. The value 0 means unlimited. This value can only be set if the type is a relation and no instances would invalidate this restriction.
Maximum versions setMaxVersions(long maxVersions) X X Set the max. number of instance versions to keep, if negative unlimited, 0 does not keep any versions.
Mode setMode(TypeMode mode) X (X) Set if this type is to be used as a regular type or as a relation. Changing the mode is currently only allowed if no content instance exist. Possible modes are:
  • Content: The "regular" type
  • Relation: Type used as relation
Name setName(String name) X X The name of the type. Has to be unique.
Permissions setPermissions(byte permissions) X X Set the permissions to check. The parameter contains the bitcoded types of permissions that should be checked. Please use the setUseXXXPermission()-convenience methods, where XXX is Type, Property, Step or Instance. If you want to use bit coded permissions, use these constants:
  • FxPermissionUtils.PERM_MASK_TYPE
  • FxPermissionUtils.PERM_MASK_PROPERTY
  • FxPermissionUtils.PERM_MASK_STEP
  • FxPermissionUtils.PERM_MASK_INSTANCE
Remove instances with relation types setRemoveInstancesWithRelationTypes(boolean removeInstancesWithRelationTypes) - (X) Only applies to relations: If relation entries are removed (for instance, you no longer want to relate Type A and B using this relation), all instances of this relation type that relate the removed FxTypeRelation will also be removed.
State setState(TypeState state) X X Changing the state allows to (de-)activate a type.
  • Available
  • Locked - temporary unavailabilty, should only be set from [fleXive] internally to allow for timeconsuming processing.
  • Unvailable
Track history setTrackHistory(boolean trackHistory) X X Enables history tracking (will log changes to the type itself or instances). How long history entries are kept can be set with setHistoryAge(long)
Use instance permissions setUseInstancePermissions(boolean use) X X Should instance permissions be checked? If enabled, the ACL assigned to instances will be checked.
Use property permissions setUsePropertyPermissions(boolean use) X X Should property (assignment) permissions be checked? If enabled, the ACL assigned to property assignments will be checked. Property permission checks are disabled by default and should only be used if really necessary (i.e. if you want to hide specific company or department internal properties from users that under normal circumstances should be allowed to read the instance).
Use step permissions setUseStepPermissions(boolean use) X X Should step permissions be checked? If enabled, the ACL assigned to workflow steps will be checked. Enable these checks if you want to prevent users from seeing/using instances in certain steps (i.e. an editor should not be allowed to edit already published articles - this is something only users from the quality assurance department should be allowed to do).
Use type permissions setUseTypePermissions(boolean use) X X Should type permissions be checked? If enabled, the ACL assigned to this type will be checked. Disabling this check, will allow everyone to create or remove instances of this type (if instance permission checks are enabled, they will of course still be checked in the case of a removal).
Allow multiple instance ACLs setMultipleContentACLs(boolean value) X X If true, multiple content instance ACLs are allowed for content instances of this type.
Workflow setWorkflow(Workflow workflow) X (X) Assign a workflow to this type. For existing types the workflow can only be changed if no instances exist.

In the following example we create a new type "Customer", provide a multilingual label and assign an access control list:


Another way to create a new type would be to use the GroovyTypeBuilder:


Every data type can potentially support values for different languages - depending on the properties' and property assignments' multilingual support settings.

Table 6.4. [fleXive] data types
Data type FxValue class Description
HTML FxHTML HTML markup. Unlimited in length. Offers the ability to use HTML editors in user interfaces.
String1024 FxString A String with a maximum length of 1024 characters. Use this data type in favor of Text if you don't need more than 1024 characters, since usually Text is stored in CLOB Database columns while String1024 uses VARCHAR columns.
Text FxString Like String1024 but unlimited in length.
Number FxNumber Numerical type corresponding to the Java Integer class.
LargeNumber FxLargeNumber Numerical type corresponding to the Java Long class.
Float FxFloat Numerical type corresponding to the Java Float class.
Double FxDouble Numerical type corresponding to the Java Double class.
Date FxDate A date corresponding to the Java Date class. Note that there is no time information saved!
DateTime FxDate A date corresponding to the Java Date class. This data type stores date and time information.
DateRange FxDateRange A date range corresponding to two Java Date class instances with a start- and enddate. Note that there is no time information saved!
DateTimeRange FxDateTimeRange A date range corresponding to two Java Date class instances with a start- and enddate. Time information is saved as well using this data type.
Boolean FxBoolean A boolean value corresponding to the Java Boolean class.
Binary FxBinary This data type stores information about a binary content and allows streaming of that content. For more information please refer to the section called “Handling binary content”
Reference FxReference A reference to a content instance, identified by its primary key (FxPK).
InlineReference - This data type is only planned but not implemented. It will allow to create contents that do not exist on their own (and can not be loaded on their own or queried for) but embedded in another content instance. Their XPath addressing will be relative to their parent group in the embedding content.
SelectOne FxSelectOne This data type allows the selection of one entry of a SelectList. See the section called “Select lists” for further information about select lists.
SelectMany FxSelectMany This data type allows the selection of many entries of a SelectList. See the section called “Select lists” for further information about select lists.

Working with binary content is like working with ordinary input- and outputstreams in Java. For uploading a binary an InputStream and for downloading an OutputStream has to be passed. Transfer of binaries is handled by [fleXive]'s own streaming framework fxStream. It uses nonblocking tcp sockets as transport medium if the client and server part exist in different virtual machines and is able to detect if they run within the same VM for optimal performance.


Select lists usually contain a set of related select items, which are used in GUIs to enable the user to make a selection of one or more of these items. [fleXive] allows in-memory creation of slim select lists for quick GUI display, as well as defining and persisting fully fledged deeply nested select lists. Names of selectlist items have to be unique within their respective list.

While only users in the role of SelectListEditor may create, update and delete select lists, select list items are handled differently. Whether a specific user is permitted to add itmes to and remove items from a specific select list is handled by the createItem ACL of the select list. Whether users may read, edit, select and deselect a specific select list item is handled by the ACL of the select item itsself. The operations and relevant permissions are specified in Table 6.7, “Relevant permissions for working with select list items”.

Table 6.7. Relevant permissions for working with select list items
Operation ACL Permission Description
Creating a select list item FxSelectList.createItemACL CREATE The createItemACL of the item's select list controls which users may create and hence add select list items to this specific select list.
Deleting a select list item FxSelectList.createItemACL DELETE Similar to the creation of new select list items, the createItemACL of the item's select list also controls which users may remove select list items from this specific select list.
Editing a select list item FxSelectListItem.acl EDIT Whether a user may change the data of a specific select list item is controlled by the EDIT permission of the ACL of the select list item itsself.
Reading a select list item FxSelectListItem.acl READ Whether a user may read a specific select list item and its data (for exmaple in the content editor) is controlled by the READ permission of the select list item.
Adding a select list item to a selection (when working with contents) FxSelectListItem.acl READ, CREATE Whether a user may add specific select list item to his seleciton is controlled by the READ (otherwise the user wouldn't see that the item exists) and by the CREATE permission of the select list item.
Removing a select list item to a selection (when working with contents) FxSelectListItem.acl READ, DELETE Whether a user may remove specific select list item from his seleciton is controlled by the READ (otherwise the user wouldn't see that the item exists) and by the DELETE permission of the select list item.

Multiplicity - or often referred to as cardinality - defines the minimum and maximum occurance of an assignment. An assignment in the context of [fleXive] is a group- or a property assignment. Multiplictiy is implemented in the class FxMultiplicity which contains some predefined and often used constants:

  • FxMultiplicity.MULT_0_1: zero or one occurances (optional)
  • FxMultiplicity.MULT_1_1: exactly one occurance (required)
  • FxMultiplicity.MULT_0_N: zero or more occurances (optional)
  • FxMultiplicity.MULT_1_N: one or more occurances (required)

The value N means any number of occurances.

A multiplicity of 1 to 5 elements would be coded like this: new FxMultiplicity(1,5)

A property defines a name and a datatype (and some options). It can only exist (and is of relevance) if it is assigned to a type or group. The purpose of keeping properties and their assignments separate is the ability to share them and query across multiple types with a single property.

There are two ways to assign a property to an existing type or group: Either by calling FxPropertyEdit.createNew(..) method which can clone existing or create entirely new properties or by reusing an existing property assignment by calling FxPropertyAssignmentEdit.createNew(..).

Example 6.7. Creating new properties

1        AssignmentEngine assignmentEngine = EJBLookup.getAssignmentEngine();
2        ACL customerACL = CacheAdmin.getEnvironment().getACL(ACLCategory.STRUCTURE.getDefaultId());

3        FxPropertyEdit name = FxPropertyEdit.createNew("Name",
4                        new FxString("Name of the person"),
5                        new FxString("Enter the persons name"),
6                        FxMultiplicity.MULT_1_1,
7                        customerACL,
8                        FxDataType.String1024);
9        assignmentEngine.createProperty(typeId, name.setAutoUniquePropertyName(true), "/");

1

Obtain a reference to the assignment engine bean which is responsible for manipulating assignments

2

Get the default ACL used for structures

3

Create a new property with the alias "Name"

4

Label

5

Hint for user interfaces

6

Configure this property to be required (See the section called “Multiplicity” for more information)

7

Assign the ACL to be used. This ACL will only be checked if the type this property will be assigned to has property permission checks enabled

8

The data type will be a String with a maximum length of 1024 characters. See the section called “Data types” for an overview of available data types.

9

Since properties can not exist if they are not assigned to a type, we assign them to the type with the id typeId to the root group ("/" - for an example how to assign it to a group of choice seethe section called “Groups and group assignments”). Property names have to be unique but since "Name" is very likely to be used by another property already we allow [fleXive] to auto-generate a unique property name (in the form of "propertyname_"+running number) and make use of the feature that most setters return the object itself (in this case the FxPropertyEdit object) which we pass to the createProperty(..)-method. This method will create the property and assign it to the type we passed as first argument - creating a new property and property-assignment entry.


To reuse an existing property-assignment is even simpler:


One of the most important concepts of [fleXive] is the relation between properties (or groups) and their assignments to types (or groups). As mentioned in the introduction to this chapter: "A property defines a name and a datatype (and some options). It can only exist (and is of relevance) if it is assigned to a type or group. The purpose of keeping properties and their assignments separate is the ability to share them and query across multiple types with a single property."

Essentially this means, that while a property does have unique attributes (which can be overwritten), its assignments to different types imply that these attributes can differ from the "original". As soon as a property has no more assignments (i.e. is no longer associated to a type), it is removed from [fleXive] The ability to further assign the same property to multiple types enables [fleXive] to carry out queries for these properties and returning results from any type they are attached to.

A simple, theoretical example: Given the types "A" and "B", and property "T" having its label set to "foo". First, "T" is assigned to "A" Second, "T" is assigned to "B" and the assignment's label set to "bar". Step I.) Querying "T"'s label (i.e. loading the FxProperty) will yield "foo". Step II.) Querying for "T"'s assignment to "B" will yield "bar". Step III.) After deleting the assignment of "T" to "A", the query in Step I.) will still yield "foo".

This concept is best explained by giving a comprehensive example using actual [fleXive] code: The types "Person" and "Anotherperson" are created. The property firstname will first be assigned to "Person", then an assignment of the same property is made to "Anotherperson". The original property assignment is then removed from "Person" showing that the property will still retain the attributes it received during creation.

Please note that the concepts explained here also apply to groups and their assignments.

Example 6.9. Property assignment concepts

import com.flexive.shared.scripting.groovy.*
import com.flexive.shared.value.*
import com.flexive.shared.security.*
import com.flexive.shared.*
import com.flexive.shared.structure.*

new GroovyTypeBuilder().person(label: new FxString("Person"),                     1
        acl: CacheAdmin.environment.getACL(ACLCategory.STRUCTURE.defaultId),
        multilang: true) {
}
// we "reload" the "Person" type to show the means of adding properties using the
// GroovyTypeBuilder after type creation.
def builder = new GroovyTypeBuilder("Person")                                           2
builder {
    firstname(dataType: FxDataType.String1024,                                          3
            multilang: false,
            label: new FxString(FxLanguage.ENGLISH, "A person's first name"),     4
            multiplicity: FxMultiplicity.MULT_0_N)
}

new GroovyTypeBuilder().anotherperson(label: new FxString("Anotherperson"),       5
        acl: CacheAdmin.environment.getACL(ACLCategory.STRUCTURE.defaultId),
        multilang: true) {
            anotherfirstname(assignment: "PERSON/FIRSTNAME",                            6
            label: new FxString(FxLanguage.ENGLISH, "Another's first name"))      7
}

def name = ""
def type = CacheAdmin.getEnvironment().getType("person")
FxPropertyAssignment propAssign = type.getPropertyAssignment("PERSON/FIRSTNAME")
name = propAssign.getLabel()
EJBLookup.getAssignmentEngine().removeAssignment(propAss.getId(), false, false);        8


FxProperty prop = CacheAdmin.getEnvironment().getProperty("firstname");                 9
return "Removed assigned (label): " + name + "; Retained label for property: "
    + String.valueOf(prop.getLabel())                                                   10

1

The type "Person" is created.

2

The GroovyTypeBuilder is called again loading the just created type. Incidentally this also shows how to create properties for a type using the builder after type creation.

3

Here we create / assign the property "firstname" and ..

4

.. set its label to "A person's first name".

Note that the GroovyTypeBuilder both creates an FxProperty as well as assigns it to the given type within the same block of code.

5

The type "Anotherperson" is created ..

6

.. and the firstname property is assigned to this type having the alias "anotherfirstname".

7

The label is set to "Another's first name".

8

After temporarily storing the property's label (for later reference) we remove the assignment of the property "firstname" from the type "Person".

9

Since only the assignment was removed, we can still load the "original" property.

10

We can then return both the assignment's label which was just removed, and for comparison reasons the label of the "stand-alone" property, showing they will be the same. The script will return the text: Removed assigned (label): A person's name; Retained label for property: A person's name


The following is a list of parameters that can be passed as arguments to FxPropertyEdit and FxPropertyAssignmentEdit when editing or creating a new propery/assignment:

Table 6.8. FxPropertyEdit/FxPropertyAssignmentEdit shared parameters
Parameter Method Create Edit Description
ACL setACL(ACL acl) X X The ACL which is checked when the type using this property or assignment is configured to check property permissions. Setting this value for FxPropertyAssignmentEdit is only allowed if the referenced property allows to override its ACL.
Hint setHint(FxString hint) X X Set a hint text to be displayed in user interfaces.
In overview setInOverview(boolean inOverview) X X Display in overviews. This is an option for user interfaces and a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_SHOW_OVERVIEW ("SHOW.OVERVIEW") is used. The property can restrict this setting from being overwritten in an assignment.
Label setLabel(FxString label) X X Set a label text to be displayed in user interfaces.
Multilingual setMultiLang(boolean multiLang) X X Allow multilingual values for this property. This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_MULTILANG ("MULTILANG") is used. The property can restrict this setting from being overwritten in an assignment.
Multiline setMultiLine(boolean multiLine) X X A hint for user interfaces if this property should be rendered using input elements with multiple lines. Useful for String/Text based properties (See the section called “Data types”) which should be displayed in a textarea instead of a single input field. Decision how to render the component is up to the user interface. This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_MULTILINE ("MULTILINE") is used. The property can restrict this setting from being overwritten in an assignment.
Multiplicity setMultiplicity(FxMultiplicity multiplicity) X (X) Set the multiplicity of this property. Can only be changed if no instances exist that would violate the new setting. (See the section called “Multiplicity” for more information). The property can restrict this setting from being overwritten in an assignment.
Options setOption(..) setOptionOverridable(..) clearOption(..) X X Option related operations. Seethe section called “Property and group options”.
Searchable setSearchable(boolean searchable) X X Allow user interfaces to use this propery/assignment in visual query editors. This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_SEARCHABLE ("SEARCHABLE") is used.
Use HTML editor setUseHTMLEditor(boolean useHTMLEditor) X X Hint for user interfaces to use a HTML editor when editing values of this property. Only makes sense for String/Text based data types. This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_HTML_EDITOR ("HTML.EDITOR") is used.

Table 6.9. FxPropertyEdit exclusive parameters
Parameter Method Create Edit Description
Auto unique property name setAutoUniquePropertyName(boolean autoUniquePropertyName) X - Property names have to be unique to allow querying them. Setting this option to true will automatically choose a name that has not been used for a propery by adding an underscore and a running number to property names until it is unique. Set this option only if you do not plan on "sharing" a property between different types or dont need to query based on properties but rather property assignments.
Data type setDataType(FxDataType dataType) X - Set the data type of this property. Please see the section called “Data types” for more information.
Fulltext indexed setFulltextIndexed(boolean fulltextIndexed) X X Enable fulltext indexing and queries for a property. See the section called “Fulltext search” for more information.
Name setName(String name) X - Set the name of this property. This name is used in assignments as a proposal for the XPath alias (unless a different one is requested). Currently the name can not be changed for existing properties. To query across assignments using the same property, this name is used.
Overridable ACL setOverrideACL(boolean overrideACL) X X Restrict if assignments may use an ACL different from the one defined for the property. If set to false an assignment may still set an ACL but the ACL of the property is used and the assignments is ignored.
Overridable HTML editor setOverrideHTMLEditor(boolean overrideHTMLEditor) X X Restrict assignment to override the HTML editor option (User interface hint). This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_HTML_EDITOR ("HTML.EDITOR") is used.
Overridable Multilinguality setOverrideMultiLang(boolean overrideMultiLang) X X Restrict assignment to override the multilinguality option (allow multilingual values). This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_MULTILANG ("MULTILANG") is used.
Overridable Multiline setOverrideMultiLine(boolean overrideMultiLine) X X Restrict assignment to override the multiline option (User interface hint). This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_MULTILINE ("MULTILINE") is used.
Overridable multiplicity setOverrideMultiplicity(boolean overrideMultiplicity) X X Restrict if assignments may override the multiplicity of this property. (See the section called “Multiplicity” for more information).
Overridable Overview setOverrideOverview(boolean overrideOverview) X X Restrict assignment to override the overview option (User interface hint). This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_SHOW_OVERVIEW ("SHOW.OVERVIEW") is used.
Overridable Searchable setOverrideSearchable(boolean overrideSearchable) X X Restrict assignment to override the searchable option (User interface hint). This is a convenience method to set an option (See the section called “Property and group options”). The constant FxStructureOption.OPTION_SEARCHABLE ("SEARCHABLE") is used.
Referenced list setReferencedList(FxSelectList referencedList) X (X) If the properties data type is SelectOne or SelectMany (See the section called “Data types” for more information) the referenced selectlist (See the section called “Select lists”) can be assigned. Updating an existing property is only allowed if no data instances using the original selectlist exist.
Referenced type setReferencedType(FxType referencedType) X (X) If the properties data type is Reference (See the section called “Data types” for more information) the referenced type (See the section called “Types”) can be assigned. Updating an existing property is only allowed if no data instances using the original type exist.
Unique mode setUniqueMode(UniqueMode uniqueMode) X (X) Set the uniqueness level of this property. May only be changed if no content instances using this property exist. (See the section called “Uniqueness of values” for more information).

Table 6.10. FxPropertyAssignmentEdit exclusive parameters
Parameter Method Create Edit Description
Alias setAlias(String alias) X - Set the alias of a property assignment. Property assignments may define an alias to allow multiple use of the same property but using a different name. The alias is the rightmost part of the XPath used to address an assignment. Changing an alias for existing assignments is not supported (yet).
Default language setDefaultLanguage(int language) X X Defining a (optional) default language preselects this language in multilingual values as the default language.
Default multiplicity setDefaultMultiplicity(int defaultMultiplicity) X X The default multiplicity determines how many values will be initialized for an assignment. Useful in user interfaces to pre-create a set of entries instead of one.
Enabled setEnabled(boolean enabled) X (X) Enables or disables a property assignment - making it unavailable to editors, etc. Updating an existing assignment is currently experimental and might have side-effects ...
Parent group assignment setParentGroupAssignment(FxGroupAssignment parent) X - If this assignment is assigned to a group, the assignment of the parent group (in the context of the current type)
Position setPosition(int position) X X Set the position of the assignment (within the same parent group). Changing an assignment's position will be update all other affected assignments within the same group. Invalid values will be adjusted (to 0 or the max. possible position)

A group basically only defines a name (and some options). It can only exist (and is of relevance) if it is assigned to a type or another group. The purpose of keeping groups and their assignments separate is the ability to share them and be consistent with how properties and property assignments are handled.

Just like using properties, there are two ways to assign a group to an existing type or another group: Either by calling FxGroupEdit.createNew(..) method which can clone existing or create entirely new groups or by reusing an existing group assignment by calling FxGroupAssignmentEdit.createNew(..).

Example 6.10. Creating a new group

1        AssignmentEngine assignmentEngine = EJBLookup.getAssignmentEngine();

2        assignmentEngine.createGroup(
3                typeId,
4                FxGroupEdit.createNew(
5                        "Address",
6                        new FxString("The customers address"),
7                        new FxString("Enter the customers address here"),
8                        true,
9                        FxMultiplicity.MULT_1_1).
10                        setAssignmentGroupMode(GroupMode.AnyOf),
11                "/");

12        FxPropertyEdit street = FxPropertyEdit.createNew(...);
13        FxPropertyEdit zip = FxPropertyEdit.createNew(...);
14        assignmentEngine.createProperty(typeId, street, "/Address");
15        assignmentEngine.createProperty(typeId, zip, "/Address");

1

Obtain a reference to the assignment engine which is needed to create groups, properties and (of course) assignments

2

We're about to create a new group

3

Since groups can not be created without assigning them to a type, we have to provide the id of the type we want to assign this group to.

4

The second parameter to AssignmentEngine.createNew(..) is a new FxGroupEdit instance.

5

"Address" is the name we chose for the new group

6

The label (for user interfaces)

7

The hint (for user interfaces again)

8

This parameter allows overriding the multiplicity assigned in the next line by assignments to the group

9

We make the group required, setting the multiplictiy to 1..1 (See the section called “Multiplicity” for more information)

10

This parameter is optional, since it is the default value. We set the group mode to allow any of the group's children to be present. An alternative would be OneOf where only one child of the group may be set. (See the section called “Group modes” for more information)

11

We need to provide the XPath relative to the root group of the type where we want to assign the group to. Using "/" will assign it directly to the root group.

12

We create a property called "Street" which we want to assign to the address group later.

13

Same for the property "ZIP"

14

The "Street" property is created like in the section called “Properties and property assignments”, but we assign it to our new created group "/Address"

15

And again for the "ZIP" code


Here's another example for creating groups using the GroovyTypeBuilder and for attaching content using the GroovyContentBuilder:

Example 6.11. Creating a new group using the GroovyTypeBuilder

        import com.flexive.shared.scripting.groovy.*
        import com.flexive.shared.value.*
        import com.flexive.shared.security.*
        import com.flexive.shared.*
        import com.flexive.shared.structure.*

1      new GroovyTypeBuilder().person(label: new FxString("Person"),
2                acl: CacheAdmin.environment.getACL(ACLCategory.STRUCTURE.defaultId),
3                multilang: true) {
4                    firstname(dataType: FxDataType.String1024,
                        multilang: false,
                        label: new FxString(FxLanguage.ENGLISH, "First name"),
                        multiplicity: FxMultiplicity.MULT_0_N)

5                    lastname(assignment: "PERSON/FIRSTNAME",
                       label: new FxString(FxLanguage.ENGLISH, "Last name"),
                       hint: new FxString(FxLanguage.ENGLISH, "Last name required"),
                       multiplicity: FxMultiplicity.MULT_1_N)

6                    ADDRESS(label: new FxString(FxLanguage.ENGLISH, "Address"),
                        multiplicity: FxMultiplicity.MULT_0_N) {

7                         street(dataType: FxDataType.String1024,
                             label: new FxString(FxLanguage.ENGLISH, "Street (Nr)"),
                             multiplicity: FxMultiplicity.MULT_0_N)
                     }
        }

8      def builder = new GroovyContentBuilder("PERSON")

9      builder {
10           firstname("John")
11           lastname("Doe")
12           address {
13               street(new FxString(false, "Ameaningfulstreetname 444"))
            }
         }
14       EJBLookup.getContentEngine().save(builder.getContent())

1

Create the type "Person" using the GroovyTypeBuilder ..

2

.. use the default ACLs ..

3

.. and set the type to support multiple languages.

4

Create the first property "firstname".

5

Another property for the last name (implicitly required because auf the default multiplicity of 1..N), which is a derived assignment from "FIRSTNAME".

6

Here, the group "Address" having the XPath "ADDRESS" is created. Important: UPPERCASE LETTERS (Either the whole group name or simply the first letter, as in "Address") always denote the creation of a Group.

7

The group's only property: "street".

8

Retrieve a GroovyContentBuilder instance.

9

Call the builder passing the parameters (XPathname([contentValue]):

10

Set the firstname to "John".

11

Set the lastname to "Doe".

12

"Open up" the group's XPath value using "address".

13

Pass the value "Ameaningfulstreetname 444" to the XPath ADDRESS/STREET

14

Save the content by retrieving the ContentEngine EJB and calling its save() method.


The following is a list of parameters that can be passed as arguments to FxGroupEdit and FxGroupyAssignmentEdit when editing or creating a new group/assignment:

Table 6.11. FxGroupEdit/FxGroupAssignmentEdit shared parameters
Parameter Method Create Edit Description
Assignment GroupMode setAssignmentGroupMode(GroupMode mode) X (X) Set the group mode to allow any of its possible children or just one to be present. Can only be changed for existing groups/assignments if no instances exist (See the section called “Group modes” for more information)
Hint setHint(FxString hint) X X Set a hint text to be displayed in user interfaces.
Label setLabel(FxString label) X X Set a label text to be displayed in user interfaces.
Multiplicity setMultiplicity(FxMultiplicity multiplicity) X (X) Set the multiplicity of this group. Can only be changed if no instances exist that would violate the new setting. (See the section called “Multiplicity” for more information). The group can restrict this setting from being overwritten in an assignment.
Options setOption(..) setOptionOverridable(..) clearOption(..) X X Option related operations. Seethe section called “Property and group options”.

Table 6.12. FxGroupEdit exclusive parameters
Parameter Method Create Edit Description
Name setName(String name) X - Set the name of this group. This name is used in assignments as a proposal for the XPath alias (unless a different one is requested). Currently the name can not be changed for an existing group.
Overridable multiplicity setOverrideMultiplicity(boolean overrideMultiplicity) X X Restrict if assignments may override the multiplicity of this group. (See the section called “Multiplicity” for more information).

Table 6.13. FxGroupAssignmentEdit exclusive parameters
Parameter Method Create Edit Description
Alias setAlias(String alias) X - Set the alias of a group assignment. Group assignments may define an alias to allow multiple use of the same group but using a different name. The alias is part of the XPath and is used to address an assignment. Changing an alias for existing assignments is not supported (yet).
Default multiplicity setDefaultMultiplicity(int defaultMultiplicity) X X The default multiplicity determines how many values will be initialized for an assignment (i.e. how many groups are created upon initialization). Useful in user interfaces to pre-create a set of entries instead of one.
Enabled setEnabled(boolean enabled) X (X) Enables or disables a group assignment - making it unavailable to editors, etc. Updating an existing assignment is currently experimental and might have side-effects ...
Parent group assignment setParentGroupAssignment(FxGroupAssignment parent) X - If this assignment is assigned to a group, the assignment of the parent group (in the context of the current type)
Position setPosition(int position) X X Set the position of the assignment (within the same parent group). Changing an assignments position will be upate all affected other assignments within the same group. Invalid values will be adjusted (to 0 or the max. possible position)

Both properties and groups allow the definition of options. These options can hold any arbitrary String or Boolean value and, if defined, the assignments to the property or group may override the value. The name of an option must be unique. See the API documentation of class FxStructureOption for more details.

The following options are currently actively supported:

Table 6.14. Supported options
Constant Value Description
MULTILANG Value supports multiple languages ( true / false )
SHOW.OVERVIEW Values are shown in UI overview components ( true / false )
HTML.EDITOR Value can be edited using an HTML editor in user interfaces ( true / false )
SEARCHABLE Values can be queried (this is just a hint for user interfaces!) ( true / false )
MAXLENGTH Values that support a maximum input length (currently only String1024 and Text ) will be rendered with input length restrictions when editing.
MULTILINE Render a textarea instead of a single input line. If the value is greater than 1 it determines the number of rows.
REFERENCE.SELECTONE Render a select list with all valid choices for reference properties (properties referencing other contents).
SELECTMANY.CHECKBOXES Render checkboxes instead of a multi-select list for FxSelectMany properties.

The GroovyTypeBuilder ("GTB") provides a simple means for structure creation in [fleXive] using the Groovy scripting language. The GTB is based on Groovy's builder support, enabling us to easily create and manipulate [fleXive]'s hierarchical structures. Here is what the GTB can do (for you):

  • Create a structure: types, derived types, properties & groups and their respective assignments
  • Change a structure (1): Assignment attribute changes (if allowed or overridable)
  • Change a structure (2): Create additional assignments within a given type, "walk through" an existing structure

Structural or assignment changes pertain to any element within an existing type, with the exception of types themselves (please refer to the examples in the section called “GroovyTypeBuilder Usage Examples” for further reference).

A simple example of the GTB can be seen below. We create the type "PERSON" having one attribute "NAME":


Based on Groovy, a familiarity with its syntax is an asset, but not a requirement to understand the very simple syntax rules for the GTB.

General rules:

  • Properties have to start with a lower-case letter
  • Groups have to start with an upper-case letter
  • (Empty) Groups can either be denoted w/o parentheses (incl. curly braces), as in
    Groupname {
    }
                        
    or have parentheses w/o curly braces, as in
    Groupname ()
                        
  • Attributes for types, properties, groups and their respective assignments have to be inside the parentheses following the element's name. Attributes are separated by commas ",".
    propertyname (label: new FxString("Property label"), multilang: false)
                        

Creation and change of structural elements

The following is a list of all available attributes for the GroovyTypeBuilder. The parameters correspond to the type/property/group parameters mentioned in the section called “Structure Engine” Parameters / attributes are split up into the following categories:

  • Type attributes: these apply to types only
  • Property & group common attributes: these apply both to the creation of new properties and to groups
  • Property attributes: these apply to the creation of new properties
  • Group attributes: these apply to the creation of new groups
  • Property & group assignment common attributes: these apply to property group assignments and changes thereof
  • Property assignment attributes: these apply to property assignments or changes thereof
  • Group assignment attributes: these apply to group assignments or changes thereof

As mentioned inthe section called “GroovyTypeBuilder Syntax”, all attributes are called via the following syntax:

[STRUCTURENAME] ([attribute]: [value] [, ..])

E.g: firstname(multiLang: false, label: new FxString(true, "First name"))

Warning

Attributes are CASE-SENSITIVE.

Attributes in the wrong case will be ignored, misspelled attributes *might* be interpreted as generic structure options.

Override options which are not explicitly set will by default return "true". The following overrides are affected: "overrideMultiplicity", "overrideACL", "overrideSearchable", "overrideMultiline", "overrideInOverview", "overrideMultilang", "overrideMaxLength", "overrideUseHtmlEditor"

Guarantee: The GTB guarantees that changes to assignments will only affect the attributes parameterised in the call to the GTB. (i.e. a change to the "label" has no effect on any other attributes, an "empty" call to an existing assignment does not affect the assignment at all).

Hint: Examples might omit part of the code.

Table 6.15. Type Attributes
Attribute Input Example Description
acl String or ACL testtype(acl: "Default Structure ACL") or testtype(acl: CacheAdmin.getEnvironment().getACL(ACLCategory.STRUCTURE.getDefaultId()) Sets the access control list for the given type. If not given, the "Default Structure ACL" is used
generalACL String or ACL new GroovyTypeBuilder().testtype(acl: "Default Structure ACL", generalACL: "Custom ACL") { prop1() prop2(acl: "Default Structure ACL") } Sets a general (ACLCategory.STRUCTURE) ACL which is valid for all (newly) created property assignments within the type. A given "acl" will override the "generalACL"
defaultInstanceACL String or ACL Providing an instance ACL named "Foobar Instance ACL" exists: new GroovyTypeBuilder().testtype(defaultInstanceACL: "Foobar Instance ACL") { ... } Sets a default content instance ACL for the given typ
label FxString testtype(label: new FxString(true, "Property 01")) Sets the type's label. If not given, the element's name is used (code example: "testtype"
parentTypeName String testtype(parentTypeName: "ROOT") Creates a derived type from the given parentTypeName.
languageMode LanguageMode testtype(languageMode: LanguageMode.Single Determines how the type handles languages
typeMode TypeMode testtype(typeMode: TypeMode.Relation) Sets the mode of an FxType
trackHistory Boolean testtype(trackHistory: true) Enables history tracking for a type.
historyAge Long testtype(trackHistory: true, historyAge: 10L) Sets the number of history entries. Only used in conjunction with "trackHistory"
maxVersions Long testtype(maxVersions: 5L) Sets the number of versions to keep.
useInstancePermissions Boolean testtype(useInstancePermissions: true) Use instance permissions
usePropertyPermissions Boolean testtype(usePropertyPermissions: true) Use property permissions
useStepPermissions Boolean testtype(useStepPermissions: true) Use step permissions
useTypePermissions Boolean testtype(useTypePermissions: true) Use type permissions
usePermissions Boolean testtype(usePermissions: true) Use all permissions if set to "true"
workflow String or Workflow testtype(workflow: "Editor Workflow") Set the given Workflow for the type (Workflow must exist)
[GENERIC STRUCTURE OPTION] String new GroovyTypeBuilder().ford(COLOUR:"black") Set a generic option for the given type
[GENERIC STRUCTURE OPTIONS] as a List: "structureOptions" List<FxStructureOption>

def myOptions = new GroovyOptionBuilder().opt1(value: true) { opt2(value: "An option value", isInherited: false) }

testtype(structureOptions: myOptions)

Set the type's options via a List of FxStructureOptions. The structureoptions can, for instance, be created using the GroovyOptionBuilder (refer to JavaDoc f. instructions)
icon FxReference testtype(icon: new FxReference([example omitted for brevity]...)) Set an icon for the given type
Table 6.16. Properties and Groups - Common Attributes (Property / Group Creation)
Attribute Input Example Description
label FxString prop(label: new FxString(true, "Property 01")) Sets the property's label. If not given, the element's name is used (code example: "prop")
name String testprop(name: "myprop") Will create a property named "MYPROP". W/o the "name" attribute, the property's name would be "TESTPROP" Set the property's or group's name. The name attribute will override any name given during structure creation.
alias String address(alias: "address_a") (will create the XPath assignment "TYPENAME/ADDRESS_A" Set the alias for a given property or group. Will affect the XPath!
hint FxString Address(hint: new FxString(true, "Contains address properties")) Set the property's or group's hint attribute
multiplicity FxMultiplicity or String phonenumber(multiplicity: "0,3") Set the property's or group's multiplicity (cardinality). A default of 0..1 is assumed
defaultMultiplicity Integer Address(defaultMultiplicity: 0) Set a property's or group's default multiplicity. A default of 1 is assumed
overrideMultiplicity Boolean street(overrideMultiplicity: false) Set whether the property's or group's assignment may override the base multiplicity. A default of "true" is assumed for properties, "false" for groups.
[GENERIC STRUCTURE OPTION] String Address(label: new FxString("Address Group") "BUSINESS": true) or Address(label: new FxString(" Address Group") BUSINESS: "Telecom provider") Set a generic option for the given property
[GENERIC STRUCTURE OPTIONS] as a List: "structureOptions" List<FxStructureOption>

def myPropOptions = new GroovyOptionBuilder().foo(value: "bar") { foobar(value: "barfoo", overridable: false) barfoo(value: "foobar", overridable: false, isInherited: false) }

testtype(structureOptions: myPropOptions)

Set the group's or property's options via a List of FxStructureOptions.
Table 6.17. Exclusive property attributes (property creation)
Attribute Input Example Description
acl String or ACL street(acl: "Default Structure ACL") or street(acl: CacheAdmin.getEnvironment().getACL(ACLCategory.STRUCTURE.getDefaultId()) Sets the ACL for the given property. By default the "Default Structure ACL" is used.
overrideACL Boolean street(acl: "Default Structure ACL", overrideACL: true) The property's assignments may override the property's ACL
dataType FxDataType htmlEdit(dataType: FxDataType.HTML) Set the datatype for the given property. If not given, FxDataType.String1024 is assumed
autoUniquePropertyName Boolean name(autoUniquePropertyName: false) Automatically creates a unique property name should the same property (name) exist already. By default the attribute is "true"
fullTextIndexed Boolean note(dataType: FxDataType.Text, fullTextIndexed: false) Sets the full text search attribute for properties
multilang Boolean title(dataType: FxDataType.String1024, multilang: true) Sets the property's multilanguage attribute
overrideMultilang Boolean title(multilang: false, overrideMultilang: true) Determines if the multilang option may be overriden in assignments
overrideInOverview Boolean title(overrideInOverview: false) Assignments may override the "INOVERVIEW" option
maxLength Integer phonenumber(maxLength: 25, dataType: FxDataType.Text) Restrict the maximum length of input values. Works in conjunction with FxDataType.String1024 and FxDataType.Text
overrideMaxLength Boolean title(overrideMaxLength: false) Assignments may override the "MAXLENGTH" option.
overrideMultiline Boolean title(overrideMultiline: false) Assignments may override the "MULTILINE" option
overrideSearchable Boolean title(overrideSearchable: false) Assignments may override the "SEARCHABLE" option
overrideUseHtmlEditor Boolean htmledit(overrideUseHtmlEditor: false) Assignments may override the html editor option
searchable Boolean htmledit(searchable: false) Property can be searched
inOverview Boolean htmledit(inOverview: true) Property is in overview
useHtmlEditor Boolean numberarea(useHtmlEditor: true, dataType: FxDataType.Number) Property uses the html editor
multiline Boolean numberarea(multiline: true, dataType: FxDataType.HTML) Use a multiline input field for entering values
defaultValue FxValue title(dataType: FxDataType.String1024, defaultValue: new FxString(false, "Dr.")) Sets the default FxValue for the given property.
uniqueMode UniqueMode note(FxDataType.HTML, uniqueMode: UniqueMode.Global) Set the uniqueness of a property
referencedType FxType or String imageref(dataType: FxDataType.Reference, referencedType: "IMAGE") or imageref(dataType: FxDataType.Reference, referencedType: CacheAdmin.getEnvironment().getType("IMAGE") Sets the referenced FxType for a property
referencedList FxSelectList or String country(dataType: FxDataType.SelectOne, referencedList: "COUNTRIES" or country(dataType: FxDataType.SelectOne, referencedList: CacheAdmin.getEnvironment().getSelectList("COUNTRIES") Sets the FxSelectList for a FxDataType.SelectOne / .SelectMany property

As is the case with all assignments, the attribute settings are taken from the base assignment, any attributes listed here can be used to change them (e.g. the "label") if applicable (or if overridable)

Table 6.19. Property and Group Assignments - common attributes (property / group assignments and changes thereof)
Attribute Input Example Description
assignment String property(assignment: "ROOT/CAPTION") Create an assignment from an existing property or group assignment by specifying the XPath. When creating group assignments, also consider using "createSubAssignments" (see the the section called “Group Assignment Attributes” for further information on this attribute).
label FxString property(label: new FxString(true, "Property 01")) Set or change the assignment's label
defaultMultiplicity Integer Address(defaultMultiplicity: 0) Set a property's or group's default multiplicity IFF overrideBaseMultiplicity = "true"
alias String address(assignment: "CONTACTDATA/ADDRESS", alias: "address_a") Set the alias for a given property or group. Will also change the XPath.
hint FxString Address(hint: new FxString(true, "Contains address properties")) Set the property or group assignment's hint attribute
multiplicity FxMultiplicity or String phonenumber(multiplicity: "0,3") Set the propertys or groups assignment's multiplicity
enabled Boolean alternatePhone(assignment: "CONTACTDATA/ADDRESS/PHONENUMBER", enabled: false) Disable an assignment
[GENERIC STRUCTURE OPTION] String Address(label: new FxString("Address Group") "BUSINESS": true) or Address(label: new FxString(" Address Group") BUSINESS: "Telecom provider") Set a generic option for the given assignment
[GENERIC STRUCTURE OPTIONS] as a List: "structureOptions" List<FxStructureOption>

def myPropOptions = new GroovyOptionBuilder().foo(value: "bar") { foobar(value: "barfoo", overridable: false) barfoo(value: "foobar", overridable: false, isInherited: false) }

testtype(structureOptions: myPropOptions)

Set the group's or property's options via a List of FxStructureOptions.
Table 6.20. Exclusive property assignment attributes (assignments and changes thereof)
Attribute Input Example Description
multilang Boolean title(assinment: "CONTACTDATA/TITLE", multilang: true) Sets the property assignment's multilanguage attribute if overridable
defaultValue FxValue author(assignment: "MYBOOK/AUTHOR", defaultValue: new FxString(false, "Dr.")) Sets the default FxValue for the given assignment.
acl String or ACL street(assignment: "CONTACTDATA/ADDRESS/STREET", acl: "Default Structure ACL") or street(assignment: "CONTACTDATA/ADDRESS/STREET", acl: CacheAdmin.getEnvironment().getACL(ACLCategory.STRUCTURE.getDefaultId()) Sets the ACL for the given assignment.
defaultLanguage Long text(defaultLanguage: FxLanguage.GERMAN Set the assignment's default language
multiline Boolean text(multiline: true, dataType: FxDataType.HTML) Use a multiline input field for entering values
inOverview Boolean htmledit(inOverview: true) Property assignment is in overview
useHtmlEditor Boolean numberarea(useHtmlEditor: true, dataType: FxDataType.Number) Property assignment uses the html editor
maxLength Integer textarea(multiline: true, maxLength: 100) Restrict the maximum length of input values.
searchable Boolean htmledit(searchable: false) Property assignment can be searched
flatten Boolean Example: create a property "someprop" and activate the hierarchical storage mode for its assignment: new GroovyTypeBuilder().aTypeName() { someprop() someprop(flatten:false) } Activates or deactivates the flatstorage for a given property assignment

Several examples of using the GTB can be found throughout the reference documentation. This section further illustrates the various uses the GTB can be put to when creating or updating structural information in [fleXive].

  • Aliases

    Aliases can be assigned during element creation and can also be changed for existing assignments. However, it is not necessary to perform subsequent structure walk-throughs by calling the aliased name (albeit possible).

    Example: Create a type "TEST" having a property "NAME" with the aliased name "firstname". This will lead to an XPATH assignment of "TEST/FIRSTNAME" for the given property assignment.

    new GroovyTypeBuilder().test {
        name(alias: "firstname")
    }
                    

    The label can then be changed by employing

    def builder = new GroovyTypeBuilder("TEST")
    builder {
        name(label: new FxString("First name"))
    }
                    

    Any derived assignments MUST consider the aliased name (or its XPath, respectively):

    def builder = new GroovyTypeBuilder("TEST")
    builder {
        lastname(assignment: "TEST/FIRSTNAME")
    }
                    

    As mentioned above, an alias can also be changed for existing elements:

    def builder = new GroovyTypeBuilder("TEST")
    builder {
        name(alias: "name")
    }
                    

    .. which would alter the XPath of the above property assignment to "TEST/NAME"

  • Aliased assignments from other types

    A word of caution: Calling aliased assignments from other types will not work (this mainly has to do with the way the GTB has to "guess" where it is within a structure and what it is looking for & also due to the way that structure traversal works).

    Example: A structure with an aliased assignment from "ROOT/CAPTION"

    new GroovyTypeBuilder().test {
        caption(assignment: "ROOT/CAPTION", alias: "caption_alias")
    }
                    

    Now we try to call the same structure again:

    def builder = new GroovyTypeBuilder("TEST")
    builder {
        caption()
    }
                    

    This yields a NEW property within "TEST" by the name of "CAPTION"

    Q: How can I go about changing an aliased assignmnent (from another type)?

    A: Use the alias instead of the property's name! Example:

    def builder = new GroovyTypeBuilder("TEST")
    builder {
        caption_alias(label: new FxString("My derived caption"))
    }
                    

  • AutoUniquePropertyName / Alias Caveats

    Due to the inherent "update-feature" of the GTB, it is of utmost importance to understand how the Builder handles the creation of properties having the SAME name within a given structure. This is best explained by the following examples.

    def builder = new GroovyTypeBuilder().test {
        prop1()
        prop1()
    }
                        

    The above example will create "Prop1" having the default attribute values, the second call to prop1() will NEITHER create a new property (unique name: "PROP_1") NOR update the existing one.

    def builder = new GroovyTypeBuilder().test {
        prop1()
        prop1(dataType: FxDataType.Text)
    }
                            

    In the above example, an attempt is made to create a second property with the autoUniquePropertyName "PROP1_1" This, however, will fail since the generated XPATH for the respective property assignment will be equal to the XPath of the original "PROP1" assignment (XPaths provide a UNIQUE way to address assignments, therefore no equal XPaths can exist within the same hierarchical level).

    Hence the correct way to go about this is to use an alias (which will also set the XPath accordingly):

    def builder = new GroovyTypeBuilder().test {
        prop1()
        prop1(dataType: FxDataType.Text, alias: "prop1alias")
    }
                            

    If, on the other hand, the new property (having the same name as an existing one) resides within a different hierarchical level of the given structure, the alias attribute (i.e. setting a different XPath) can be omitted:

    def builder = new GroovyTypeBuilder().test {
        prop1()
        Group1 {
            prop1()
        }
    }
                            

  • Assignment Paths

    When creating assignments from properties / groups, either the full XPath or a relative XPath can be used to denote the base assignment. Where "relative" implies, that type names can be omitted.

    Example 1: full XPath (capitalising the XPath is not necessary)

    def builder = new GroovyTypeBuilder().test {
        prop1()
        Group1 {
            prop1(assignment: "TEST/PROP1")
        }
    }
                            

    Example 2: "relative" XPath

    def builder = new GroovyTypeBuilder().test {
        prop1()
        Group1 {
            prop1(assignment: "/prop1")
        }
    }
                            

The GroovyOptionBuilder ("GOB") provides a means for creating Lists of FxStructureOptions using Groovy. Just like the GTB, the GOB extends Groovy's builder support class. Let us get straight to the examples to demonstrate how the GOB works:

Considerations

  • The GroovyOptionBuilder will always return a List of FxStructureOptions
  • It is recommended to always quote the names of the options, e.g. "MYOPTION"
  • The options "overridable" and "isInherited" are true by default



[1] Imagine an online-shop scenario with different kinds of articles, each implemented using their own type. Something they have in common is their name. Instead of having to build a query for searching the name property that is an OR-construct including all involved types it would be easier to assign to all types a property called "name" and query this property instead of the assignments.