Cloud Software Group, Inc. EBX®
Documentation > Developer Guide > Data model
Navigation mode Documentation > Developer Guide > Data model

# Tables and relationships

## Tables

### Overview

TIBCO EBX® supports the features of relational database tables, including the handling of large volumes of records, and identification by primary key.

Tables provide many benefits that are not offered by aggregated lists. Beyond relational capabilities, some features that tables provide are:

- filters and searches;

- sorting, views and hierarchies;

- identity constraints: primary keys, foreign keys and uniqueness constraints;

- specific permissions for creation, modification, and deletion;

- dynamic and contextual permissions at the individual record level;

- detailed comparison and merge;

- ability to have inheritance at the record level (see dataset inheritance);

- performance and memory optimization.

##### See also

- Entity mappings
- Foreign keys
- Associations
- Linked fields
- Working with existing datasets
- Simple tabular views
- Hierarchical views
- History

### Declaration

A table element, which is an element with maxOccurs > 1, is declared by adding the following annotation:

    <xs:annotation>
    	<xs:appinfo>
    		<osd:table>
    			<primaryKeys>/pathToField1 /pathToField...n</primaryKeys>
    		</osd:table>
    	</xs:appinfo>
    </xs:annotation>

##### Note

A default entity name is associated to the table if it does not have one explicitly set in the data model. The table's name is used as its default entity name. Entity names allow to refer to tables in SQL requests and Data Service operations using unique names instead of their paths by defining suffixes for WSDL operations and aliases for SQL requests. See Entity mappings for more informations.

### Common properties

Element | Description | Required
--- | --- | ---
`primaryKeys` | Specifies the primary key fields of the table. Each field of the primary key must be denoted by its absolute XPath notation that starts just under the root element of the table. If there are multiple fields in the primary key, the list is delimited by whitespace. Note: Whitespaces in primary keys of type `xs:string` are handled differently. See Whitespace handling for primary keys of type string. | Yes.
`defaultLabel` | Defines the end-user display of records. Multiple variants can be specified: A static non-localized expression is defined using the `defaultLabel` element, for example: `<defaultLabel>Product: ${./productCode}</defaultLabel>` Static localized expressions are specified using the `defaultLabel` element with the attribute `xml:lang`, for example: `<defaultLabel xml:lang="fr-FR">Produit : ${./productCode}</defaultLabel>` `<defaultLabel xml:lang="en-US">Product: ${./productCode}</defaultLabel>` A JavaBean that implements the interface `UILabelRenderer` and/or the interface `UILabelRendererForHierarchy`. The JavaBean is specified by means of the attribute `osd:class`, for example: `<defaultLabel osd:class="com.wombat.MyLabel"></defaultLabel>` ##### Attention Since the end-user display should be sortable, only fields that use sortable search strategies are allowed in static expressions. Note: The priority of the tags when displaying the user interface is the following: `defaultLabel` tags with a JavaBean (but it is not allowed to define several renderers of the same type); `defaultLabel` tags with a static localized expression using the `xml:lang` attribute; `defaultLabel` tags with a static non-localized expression. Attention: Access rights defined on associated datasets are not applied when displaying record labels. Fields that are usually hidden due to access rights restrictions will be displayed in labels. | No.
`recordForm` | Defines a specific component for customizing the record form in a dataset. This component is defined using a JavaBean that extends `UIForm` or implements `UserServiceRecordFormFactory`. The JavaBean is specified by means of the attribute `osd:class`, for example: `<recordForm osd:class="com.wombat.MyRecordForm"/>` | No.

### Example

Below is an example of a product catalog:

    <xs:element name="Products" minOccurs="0" maxOccurs="unbounded">
    	 <xs:annotation>
    		 <xs:documentation>
    			 <osd:label>Product Table </osd:label>
    			 <osd:description>List of products in Catalog </osd:description>
    		 </xs:documentation>
    	 </xs:annotation>
    	 <xs:complexType>
    	 <xs:annotation>
    		 <xs:appinfo>
    			 <osd:table>
    				 <primaryKeys>./productRange /productCode</primaryKeys>
    				 <index name="indexProductCode">/productCode</index>
    			 </osd:table>
    		 </xs:appinfo>
    	 </xs:annotation>
    		 <xs:sequence>
    			 <xs:element name="productRange" type="xs:string"/><!-- key -->
    			 <xs:element name="productCode" type="xs:string"/><!-- key -->
    			 <xs:element name="productLabel" type="xs:string"/>
    			 <xs:element name="productDescription" type="xs:string"/>
    			 <xs:element name="productWeight" type="xs:int"/>
    			 <xs:element name="productType" type="xs:string"/>
    			 <xs:element name="productCreationDate" type="xs:date"/>
    		 </xs:sequence>
    	 </xs:complexType>
    </xs:element>

    <xs:element name="Catalogs" minOccurs="0" maxOccurs="unbounded">
    	 <xs:annotation>
    		 <xs:documentation>
    			 <osd:label>Catalog Table</osd:label>
    			 <osd:description>List of catalogs</osd:description>
    		 </xs:documentation>
    	 </xs:annotation>
    	 <xs:complexType>
    		 <xs:annotation>
    			 <xs:appinfo>
    				 <osd:table>
    					 <primaryKeys>/catalogId</primaryKeys>
    				 </osd:table>
    			 </xs:appinfo>
    		 </xs:annotation>
    		 <xs:sequence>
    			 <xs:element name="catalogId" type="xs:string"/><!-- key -->
    			 <xs:element name="catalogLabel" type="xs:string"/>
    			 <xs:element name="catalogDescription" type="xs:string"/>
    			 <xs:element name="catalogType" type="xs:string"/>
    			 <xs:element name="catalogPublicationDate" type="xs:date"/>
    		 </xs:sequence>
    	 </xs:complexType>
    </xs:element>

### Properties related to dataset inheritance

The following properties are only valid in the context of dataset inheritance:

Element | Description | Required
--- | --- | ---
`onDelete-deleteOccultingChildren` | Specifies whether, upon record deletion, child records in occulting mode are also to be deleted. Valid values are: `never` or `always`. | No, default is `never`.
`mayCreateRoot` | Specifies whether root record creation is allowed. The expression must follow the syntax below. See definition modes. | No, default is `always`.
`mayCreateOverwriting` | Specifies whether records are allowed to be overwritten in child datasets. The expression must follow the syntax below. See definition modes. | No, default is `always`.
`mayCreateOcculting` | Specifies whether records are allowed to be occulted in child datasets. The expression must follow the syntax below. See definition modes. | No, default is `always`.
`mayDuplicate` | Specifies whether record duplication is allowed. The expression must follow the syntax below. | No, default is `always`.
`mayDelete` | Specifies whether record deletion is allowed. The expression must follow the syntax below. | No, default is `always`.

The `may...` expressions specify when the action is possible, though the ultimate availability of the action also depends on the user access rights. The expressions have the following syntax:

> expression ::= always | never | <condition>*

> condition ::= [root:yes | root:no]

> "always": the operation is "always" possible (but user rights may restrict this).

> "never": the operation is never possible.

> "root:yes": the operation is possible if the record is in a root instance.

> "root:no": the operation is not possible if the record is in a root instance.

If the record does not define any specific conditions, the default is used.

##### See also

- Dataset inheritance

### Using toolbars

It is possible to define the toolbars to display in the user interface using the element `defaultView/toolbars` under `xs:annotation/appinfo/osd:table`. A toolbar allows to customize the buttons and menus to display when displaying a table view, a hierarchical view, or a record form.

The table below presents the elements that can be defined under `defaultView/toolbars`.

Element | Description | Required
--- | --- | ---
`tabularViewTop` | Defines the toolbar to use on top of the default table view. | No.
`tabularViewRow` | Defines the toolbar to use on each row of the default table view. | No.
`recordTop` | Defines the toolbar to use in the record form. | No.
`hierarchyViewTop` | Defines the toolbar to use in the default hierarchy view of the table. | No.

##### See also

- Toolbars

### Example

Below is an example of custom toolbars used by a product catalog:

    <xs:element name="Products" minOccurs="0" maxOccurs="unbounded">
    	 <xs:annotation>
    		 <xs:documentation>
    			 <osd:label>Product Table </osd:label>
    			 <osd:description>List of products in Catalog </osd:description>
    		 </xs:documentation>
    	 </xs:annotation>
    	 <xs:complexType>
    	 <xs:annotation>
    		 <xs:appinfo>
    			 <osd:table>
    				 <primaryKeys>./productRange /productCode</primaryKeys>
    				<defaultView>
    					<toolbars>
    						<tabularViewTop>toolbar_name_for_tabularViewTop</tabularViewTop>
    						<tabularViewRow>toolbar_name_for_tabularViewRow</tabularViewRow>
    						<recordTop>toolbar_name_for_recordTop</recordTop>
    						<hierarchyViewTop>toolbar_name_for_hierarchyViewTop</hierarchyViewTop>
    					</toolbars>
    				</defaultView>
    			</osd:table>
    		 </xs:appinfo>
    	 </xs:annotation>
    	...
    	 </xs:complexType>
    </xs:element>

##### Note

If a toolbar does not exist or is not available for a specific location then no toolbar will be displayed in the user interface in the corresponding location.

### Record metadata

EBX® automatically adds record metadata to a table's structure. The metadata nodes enable retrieval of the following information about a record:

- Creator.

- Creation time.

- Last modifier.

- Time of last modification.

- Unique identifier of a record (UUID). This metadata being technical it cannot be used in a custom table view, in the structured search tools and quick search.

- The definition mode of a record. This metadata being technical it cannot be used in a custom table view, in the structured search tools and quick search.

An example use for record metadata might be to display or fetch all the records created by a specific user since a specific date. This is possible:

- For business users in the user interface by:

  - Using the quick search feature to locate records by using the metadata fields as part of the search criteria.

  - Defining table views that include the desired metadata fields.

- Via the API by querying with XPath or SQL.

##### Attention

Please take note of the following points regarding metadata:

- Metadata are defined under a group with the reserved name ebx-metadata. As a consequence, the metadata won't be available in a table if it contains a group, directly under its root, with the same name. A warning displays when compiling the data model if a table defines a group with this reserved name.

- Metadata are read-only.

- Metadata are not included when exporting the content of a table to an XML or CSV file.

- By default, metadata fields are not including when instrospecting a data model using the API. You can explicitly included them using the dedicated API.

##### See also

- Metadata fields in SQL
- Technical data
- `SchemaMetadataConstants`
- `Constants.Data`

## Foreign keys

### Declaration

A reference to a table is defined using the extended facet `osd:tableRef`.

The node holding the `osd:tableRef` declaration must be of type `xs:string`.

At the instantiation, any value of the node identifies a record in the target table using its primary key syntax.

This extended facet is also interpreted as an enumeration whose values refer to the records in the target table.

Element | Description | Required
--- | --- | ---
`tablePath` | XPath expression that specifies the target table. | Yes.
`container` | Reference of the dataset that contains the target table. | Only if the dataspace element is defined. Otherwise, default is the current dataset.
`branch` | Reference of the dataspace that contains the container dataset. | No, default is the current dataspace or snapshot.
`display` | Custom display for presenting the selected foreign key in the current record and the sorted list of possible keys. Two variants can be specified, either pattern-based expressions, or a JavaBean if the needs are very specific: Static expressions are specified using the `display` and `pattern` elements. These static expressions can be localized using the additional attribute `xml:lang` on the `pattern` element, for example: `<display>` `<pattern>Product : ${./productCode}</pattern>` `<pattern xml:lang="fr-FR">Produit : ${./productCode}</pattern>` `<pattern xml:lang="en-US">Product: ${./productCode}</pattern>` `</display>` ##### Attention Since the display pattern should be sortable, only fields that use sortable search strategies are allowed. A JavaBean that implements the interface `TableRefDisplay`. It is specified using the attribute `osd:class`. For example: `<display osd:class="com.wombat.MyLabel"></display>` ##### Attention Quick search and sort operations in the user interface will use the raw value instead of the label of the records if a JavaBean is defined or if the target table defines a programmatic label for its records. A static expression must be defined to use in these operations the label of the records. It is not possible to define both variants on the same foreign key element. Attention: Access rights defined on associated datasets are not applied when displaying record labels. Fields that are usually hidden due to access rights restrictions will be displayed in labels. | No, if the `display` property is not specified, the table's record rendering is used.
`filter` | Specifies an additional constraint that filters the records of the target table. Two types of filters are available: An XPath filter is an XPath predicate in the target table context. It is specified using the `predicate` element. For example: `<filter><predicate>type = ${../refType}</predicate></filter>` A localized validation message can be specified using the element `validationMessage`, which will be displayed to the end-user at the validation time if a record is not accepted by the filter. A specific severity level can be defined in a nested `severity` element. The default severity is 'error'. Each localized message variant is defined in a nested `message` element with its locale in an `xml:lang` attribute. To specify a default message for unsupported locales, define a `message` element with no `xml:lang` attribute. In the user interface, the XPath filter is applied to filter a table according to the value of a foreign key field. That is, if a foreign key field specifies an XPath filter in a data model, then it will be reused in the filter pane to restrict the set of values in the associated combo-box displayed in the filter pane. However, the predicate used by the filter pane will only take into account the non-contextual parts of the predicate. A programmatic filter is a JavaBean that implements the interface `TableRefFilter`. It is specified using the attribute `osd:class`. For example: `<filter osd:class="com.wombat.MyFilter"></filter>` Additional validation messages can be specified during the setup of the programmatic filter. In the user interface, programmatic filters are not applied to filter the set of values in the associated combo-box displayed in the filter pane. However, it is possible to specify an additional XPath predicate that will be used in the filter pane of the user interface. This XPath predicate is specified during the setup of the programmatic filter using the method `TableRefFilterContext.setFilterForSearch`. ##### Note The attributes `osd:class` and the property `predicate` cannot be set simultaneously. The validation search XPath functions are forbidden on a `tableRef` filter. ##### See also JavaBean specifications `JavaBeanVersion` | No.
`validation` | Specifies localized validation messages for the `osd:tableRef` and error management policy. A specific severity level can be defined in a nested `severity` element. The default severity is 'error'. An error management policy can be defined in a nested `blocksCommit` element. The error management policy that blocks all operations does not apply to filters. That is, a foreign key constraint is not blocking if a referenced record exists but does not satisfy a foreign key filter. In this case, updates are not rejected, and a validation error will be reported. Each localized message variant is defined in a nested `message` element with its locale in an `xml:lang` attribute. To specify a default message for unsupported locales, define a `message` element with no `xml:lang` attribute. | No.

##### Attention

You can create a dataset which has a foreign key to a container that does not exist in the repository. However, the content of this dataset will not be available until the container is created. After the creation of the container, a data model refresh is required to make the dataset available. When creating a dataset that refers to a container that does not yet exist, the following limitations apply:

- Triggers defined at the dataset level are not executed.

- Default values for fields that are not contained in tables are not initialized.

- During an archive import, it is not possible to create a dataset that refers to a container that does not exist.

### Example

The example below specifies a foreign key in the 'Products' table to a record of the 'Catalogs' table.

    <xs:element name="catalog_ref" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:otherFacets>
    				<osd:tableRef>
    					<tablePath>/root/Catalogs</tablePath>
    					<display>
    						 <pattern xml:lang="en-US">Catalog: ${./catalogId}</pattern>
    						 <pattern xml:lang="fr-FR">Catalogue : ${./catalogId}</pattern>
    					</display>
    					 <validation>
    						 <severity>error</severity>
    						 <blocksCommit>onInsertUpdateOrDelete</blocksCommit>
    						 <message>A default error message</message>
    						 <message xml:lang="en-US">A localized error message</message>
    						 <message xml:lang="fr-FR">Un message d'erreur localisé</message>
    					</validation>
    				</osd:tableRef>
    			</osd:otherFacets>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

##### See also

- Table definition
- Primary key syntax
- Extraction of foreign keys (XPath predicate syntax)
- Associations
- View for advanced selection
- `SchemaNode.getFacetOnTableReference`
- `SchemaFacetTableRef`

## Associations

### Overview

An association provides an abstraction over an existing relationship in the data model, and allows an easy model-driven integration of associated objects in the user interface and in data services.

Several types of associations are supported:

- 'By foreign key' specifies the inverse relationship of an existing foreign key field.

- 'Over a link table' specifies a relationship based on an intermediate link table (such tables are often called "join tables"). This link table has to define two foreign keys, one referring to the 'source' table (the table holding the association element) and another one referring to the 'target' table.

- 'By an XPath predicate' specifies a relationship based on an XPath predicate.

For an association, it is also possible to:

- Filter associated objects by specifying an additional XPath filter.

- Configure a tabular view to define the fields that must be displayed in the associated table.

- Define how associated objects are to be rendered in forms.

- Hide/show associated objects in the data service 'select' operation. See Hiding a field in Data Services.

- Specify the minimum and maximum number of associated objects that are required.

- Add validation constraints using XPath predicates for restricting associated objects.

##### See also

- `SchemaNode.getAssociationLink`
- `SchemaNode.isAssociationNode`
- `AssociationLink`

### Declaration

Associations are defined in the data model using the XML Schema element `osd:association` under `xs:annotation/appInfo`.

Restrictions:

- An association must be a simple element of type xs:string.

- An association can only be defined inside a table.

##### Note

The "official" cardinality constraints (`minOccurs="0" maxOccurs="0"`) are required because, from an instance of XML Schema, the corresponding node is absent. In other words, an association has no value and is considered as a "virtual" element as far as XML and XML Schema is concerned.

The table below presents the elements that can be defined under `xs:annotation/appInfo/osd:association`.

Element | Description | Required
--- | --- | ---
`tableRefInverse` | Defines the properties of an association that is the inverse relationship of a foreign key. The element `fieldToSource` defines the foreign key that refers to the source table of the association. The element `fieldToSource` is mandatory and must specify a foreign key field that refers to the table containing the association. The element `fieldToSource` can be defined on a foreign key list (`maxOccurs` > 1), in that case, the list should be declared as unique with a blocking uniqueness constraint (`onInsertUpdateOrDelete`). ##### See also Blocking and non-blocking constraints Uniqueness constraints | Yes if the association is the inverse relationship of a foreign key, otherwise no.
`linkTable` | Defines the properties of an association over a link table. The element `table` specifies the link table used by the association. The element `table` is mandatory and must refer to an existing table. Important: In order to be used by an association, a link table must define a primary key that is composed of auto-incremented fields and/or the foreign key to the source or target table of the association. The element `fieldToSource` defines the foreign key that refers to the source table of the association. The element `fieldToSource` is mandatory and must specify a foreign key field that refers to the table containing the association. The element `fieldToTarget` defines the foreign key that refers to the target table of the association. The element `fieldToTarget` is mandatory and must specify a foreign key field. | Yes if the association is over a link table, otherwise no.
`xpathLink` | Defines the properties of an association that is based on an XPath predicate. The `predicate` element specifies the criteria of the association, relative to the current node. Examples: `/root/Products[catalog_ref =${../catalogId}]` or `//Products[catalog_ref =${../catalogId}]` or `../Products[catalog_ref =${../catalogId}]`. The path to the predicate, for example `../Products`, specifies the target table of the association. This part of the path is resolved with respect to the current table. It is not possible to refer to a table using a relative path if the association targets a table in another dataset. If the association depends on fields of the source table, the XPath expression predicate must include references to the elements on which it depends using the notation `${<relative-path>}` where `relative-path` is a path that identifies the element relative to the association node. See EBX® XPath supported syntax. ##### Note The validation search XPath functions are forbidden on an XPath link. | Yes if the association is based on an XPath predicate, otherwise no.
`filter` | Defines an XPath predicate to filter associated objects using the `predicate` element. For example: `<filter><predicate>type = ${../refType}</predicate></filter>` It is only possible to use fields from the source and the target tables when defining an XPath filter. That is, if it is an association over a link table, it is not possible to use fields of the link table in the XPath filter. Error message on creation: in the user interface, the record creation is blocked when a user submits a new associated record that does not comply with the filter. The error message can be customized using the element `checkOnAssociatedRecordCreation/message`. Each localized message variant is defined in a nested message element with its locale in an `xml:lang` attribute. To specify a default message for unsupported locales, define a message element with no `xml:lang` attribute. See Examples for more information on this property. ##### Note The validation search XPath functions are forbidden for association filter. | No.
`xpathFilter` | Note: Deprecated. This property has been replaced by the property `filter`. Defines an XPath predicate to filter associated objects. | No.
`recordForm` | Defines a specific component for customizing the form of an associated record. This component is defined using a JavaBean that implements `UserServiceAssociationRecordFormFactory`. The JavaBean is specified by means of the attribute `osd:class`, for example: `<recordForm osd:class="com.wombat.MyRecordFormFactory"/>` | No.

It is possible to refer to another dataset. For that, the following properties must be defined either under the element `tableRefInverse`, `linkTable` or `xpathLink` depending on the type of the association:

Element | Description | Required
--- | --- | ---
`schemaLocation` | Defines the data model containing the fields used by the association. The data model is defined using a specific URN that allows referring to embedded data models and data models packaged in modules. See `SchemaLocation` for more information about specific URNs supported by EBX®. | Yes.
`dataSet` | Defines the dataset used by the association. This dataset must use the data model specified by the element `schemaLocation`. | Yes.
`dataSpace` | Defines the dataspace containing the dataset used by the association. | No.

Important:

- When creating a dataset, you can create a dataset that defines an association to a container that does not yet exist in the repository. However, the content of this dataset will not be available immediately upon creation. After the absent container is created, a data model refresh is required in order to make the dataset available. When creating a dataset that refers to a container that does not yet exist, the following limitations apply:

  - Triggers defined at the dataset level are not executed.

  - Default values on fields outside tables are not initialized.

  - During an archive import, it is not possible to create a dataset that refers to a container that does not exist.

- The consistency of an association to another dataset is checked in the operational phase. If an association is not consistent in the context of a specific dataset then:

  - It is considered as read-only from a permission perspective. That is, the association is read-only in the user interface and the data services are hidden. Also, in the user interface it is not possible to create, delete, attach, detach, or move an associated record. However, it is possible to modify an existing associated record.

  - It is excluded from the validation of the container dataset, table or record.

### User interface integration

It is possible to define how associated objects are to be rendered in forms, using the element `osd:defaultView/displayMode` under `xs:annotation/appinfo`.

Possible values are:

- `inline`, specifies that associated records are to be rendered in the form at the same position of the association in the data model.

- `tab`, specifies that associated records are to be rendered in a specific tab.

- `link`, specifies that associated records are to be rendered in a modal window.

By default, associated records are rendered `inline` if this property is not defined.

The following example specifies that associated objects are to be rendered `inline` in the form:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		<osd:association>
    			<tableRefInverse>
    			 	<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    			</tableRefInverse>
    		</osd:association>
    		<osd:defaultView>
    			<displayMode>inline</displayMode>
    		</osd:defaultView>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

The following example specifies that associated objects are to be rendered in a specific tab:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		<osd:association>
    			<tableRefInverse>
    			 	<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    			</tableRefInverse>
    		</osd:association>
    		<osd:defaultView>
    			<displayMode>tab</displayMode>
    		</osd:defaultView>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

#### Using toolbars

It is possible to define the toolbars to display in the user interface using the element `osd:defaultView/toolbars` under `xs:annotation/appinfo`. A toolbar allows to customize the buttons and menus to display when displaying the tabular view of an association.

The table below presents the elements that can be defined under `osd:defaultView/toolbars`.

Element | Description | Required
--- | --- | ---
`tabularViewTop` | Defines the toolbar to use in the default table view of this association. | No.
`tabularViewRow` | Defines the toolbar to use for each row of the default view of this association. | No.

The following example shows how to use toolbars from the previous association between a catalog and its products:

    <xs:element name="Products" minOccurs="0" maxOccurs="0" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:association>
    				<tableRefInverse>
    					<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    				</tableRefInverse>
    			</osd:association>
    			<osd:defaultView>
    				<toolbars>
    					<tabularViewTop>toolbar_name_for_tabularViewTop</tabularViewTop>
    					<tabularViewRow>toolbar_name_for_tabularViewRow</tabularViewRow>
    				</toolbars>
    			</osd:defaultView>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

##### Note

It is only possible to use the toolbars defined in the data model containing the target table of the association. That is, if the target table of the association is defined in another data model, then it is only possible to reference a toolbar defined in this data model and not in the one holding the association.

##### See also

- Toolbars

#### Customized view of associated objects

A specific tabular view can be specified to define the fields that must be displayed in the target table. If a tabular view is not defined, all columns that a user is allowed to view, according to the granted access rights, are displayed. A tabular view is defined using the element `osd:defaultView/tabularView` under `xs:annotation/appinfo`.

The table below shows the elements that can be defined under `osd:defaultView/tabularView`.

Element | Description | Required
--- | --- | ---
`column` | Define a field of the target table to display. The specified path must be absolute from the target table and must refer to an existing field. Several `column` elements can be defined to specify the fields that are to be displayed. | No.
`sort` | Define a field that can be used to sort associated objects. Several`sort` elements can be defined to specify the fields that can be used to sort associated objects. The element `nodePath` defines the path of the field that can be used to sort associated objects. The element `isAscending` specifies whether the sort order is ascending (true) or descending (false). | No.

The following example shows how to define a tabular view from the previous association between a catalog and its products:

    <xs:element name="Products" minOccurs="0" maxOccurs="0" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:association>
    				<tableRefInverse>
    					<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    				</tableRefInverse>
    			</osd:association>
    			<osd:defaultView>
    				<tabularView>
    					<column>/productRange</column>
    					<column>/productCode</column>
    					<column>/productLabel</column>
    					<column>/productDescription</column>
    					<sort>
    					   <nodePath>/productLabel</nodePath>
    					   <isAscending>true</isAscending>
    					</sort>
    				</tabularView>
    			</osd:defaultView>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

#### Actions in the user interface

In the user interface, it is possible to perform the following actions:

- Create: it allows directly creating an object in the target table of the association. When a new object is created, it is automatically associated with the current record.

- Duplicate: allows to duplicate an object in the target table of the association. When a new object is created, it is automatically associated with the current record.

- Associate: associates an existing object with the current record. In the case of an association over a link table, a record in the link table is automatically created to materialize the link between the current record and the existing object.

- Move: associates the selected objects to a different record than the current one. In the case of an association over a link table, the previous link record is automatically deleted and a new record in the link table is automatically created to materialize the link between the selected objects and their new parent record.

- Delete: deletes selected associated objects in the target table of the association.

- Detach: breaks the semantic link between the current record and the selected associated objects. In the case of an association over a link table, the records in the link table are automatically deleted, to break the links between the current record and associated objects.

##### Note

The actions associate and detach are not available when the association is defined using an XPath predicate (element xpathLink).

##### Customized view for actions

A published view, tabular or hierarchical, can be specified to define how objects should be displayed when performing an action through the user interface. A published view is defined using the element `osd:defaultView/associationViews` under `xs:annotation/appinfo`.

The table below shows the elements that can be defined under `osd:defaultView/associationViews`.

Element | Description | Required
--- | --- | ---
`viewForAssociateAction` | Define a published view to be used when displaying the objects in the target table to be associated with the current record. The specified view must be published and created upon the target table of the association. | No.
`viewForMoveAction` | Define a published view to be used when moving an associated object to another record of the current table. The specified view must be published and created upon the current table. | No.

The following example shows how to define views from the previous association between a catalog and its products:

    <xs:element name="Products" minOccurs="0" maxOccurs="0" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:association>
    				<tableRefInverse>
    					<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    				</tableRefInverse>
    			</osd:association>
    			<osd:defaultView>
    				<associationViews>
    					<viewForAssociateAction>view_name_for_catalogs</viewForAssociateAction>
    					<viewForMoveAction>view_name_for_products</viewForMoveAction>
    				</associationViews>
    			</osd:defaultView>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

### Validation

Some controls can be defined on associations, in order to restrict associated objects. These controls are defined under the element `osd:association`.

The table below presents the controls that can be defined under xs:annotation/appInfo/osd:association.

Element | Description | Required
--- | --- | ---
`minOccurs` | Specifies the minimum number of associated objects that are required for this association. This minimum number is defined using the element `value` and must be a positive integer. | No, by default the minimum is not restricted.
`maxOccurs` | Specifies the maximum number of associated objects that are allowed for this association. This maximum number is defined by the element `value` and must be either a positive integer or the raw string `unbounded` which indicates that this maximum is not restricted. The maximum number of associated objects must be greater than the minimum number of associated objects. | No, by default the maximum is not restricted.
`constraint` | Defines an XPath predicate for restricting associated records. It is only possible to use fields from the source and the target table when defining an XPath predicate. That is, if it is an association over a link table, it is not possible to use fields of the link table in the XPath predicate. In associated datasets, a validation message of the specified severity is added and displayed to the end-user at the validation time when an associated record does not comply with the specified constraint. | No.
`validation` | A validation message can be defined under the elements `minOccurs`, `maxOccurs` and `constraint`, using the element `validation`. The severity of the validation message is specified using the element `severity`. Possible severities are: `error`, `warning` and `info`. If the severity is not specified then, by default, the severity `error` is used. A localized validation message can be specified using the element `message`, which will be displayed to the end-user at the validation time if an association does not comply with this constraint. Each localized message variant is defined in a nested message element with its locale in an `xml:lang` attribute. To specify a default message for unsupported locales, define a message element with no `xml:lang` attribute. | No.

### Data services integration

It is possible to define whether associated objects must be hidden in the Data service `select` operation. For this, the property `osd:defaultView/hiddenInDataServices` under `xs:annotation/xs:appinfo` can be set on the association. Setting the property to 'true' will hide associated objects in the Data service `select` operation. If this property is not defined then, by default, associated objects will be shown in the Data service `select` operation.

##### See also

- Hiding a field in Data Services
- Association field

### Examples

For example, the product catalog data model defined previously specifies that a product belongs to a catalog (explicitly defined by a foreign key in the 'Products' table). The reverse relationship (that a catalog has certain products) is not easily represented in XML Schema, unless the 'Catalogs' table includes the following association that is the inverse of a foreign key:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		 <osd:association>
    			<tableRefInverse>
    			 	<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    			</tableRefInverse>
    		 </osd:association>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

For an association over a link table, we can consider the previous example and bring some updates. For instance, the foreign key in the 'Products' table is deleted and the relation between a product and a catalog is redefined by a link table (named 'Catalogs_Products') that has a primary key composed of two foreign keys: one that refers to the 'Products' table (named 'productRef') and another to the 'Catalogs' table (named 'catalogRef'). The following example shows how to define an association over a link table from this new relationship:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		<osd:association>
    			<linkTable>
    			 	<table>/root/Catalogs_Products</table>
    			 	<fieldToSource>./catalogRef</fieldToSource>
    			 	<fieldToTarget>./productRef</fieldToTarget>
    			</linkTable>
    		</osd:association>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

The following example shows an association that refers to a foreign key in another dataset. In this example, the 'Products' and 'Catalogs' tables are not in the same dataset:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		 <osd:association>
    			<tableRefInverse>
    				<schemaLocation>urn:ebx:module:aModuleName:/WEB-INF/ebx/schema/products.xsd</schemaLocation>
    				<dataSet>Products</dataSet>
    			 	<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    			</tableRefInverse>
    		 </osd:association>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

The following example defines an XPath filter to associate only products of the 'Technology' type:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
       <xs:annotation>
    	  <xs:appinfo>
    		 <osd:association>
    			<tableRefInverse>
    				<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    			</tableRefInverse>
    			<filter>
    				<predicate>./productType = 'Technology'</predicate>
    				<checkOnAssociatedRecordCreation>
    					<message>A default message</message>
                        <message xml:lang="en-US">A localized message</message>
                        <message xml:lang="fr-FR">Un message localisé</message>
    				</checkOnAssociatedRecordCreation>
    			</filter>
    		 </osd:association>
    	  </xs:appinfo>
       </xs:annotation>
    </xs:element>

The following example specifies the minimum number of products that are required for a catalog:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:association>
    				<tableRefInverse>
    			 		<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    				</tableRefInverse>
     				<minOccurs>
    					<value>1</value>
    					<validation>
    						<severity>warning</severity>
    						<message xml:lang="en-US">One product should at least be associated to this catalog.</message>
    						<message xml:lang="fr-FR">Un produit doit au moins être associé à ce catalogue.</message>
    					</validation>
    				</minOccurs>
    			</osd:association>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

The following example specifies that a catalog must contain at most ten products:

    <xs:element name="products" minOccurs="0" maxOccurs="0" type="xs:string">
    	<xs:annotation>
    		<xs:appinfo>
    			<osd:association>
    				<tableRefInverse>
    					<fieldToSource>/root/Products/catalog_ref</fieldToSource>
    				</tableRefInverse>
    				<maxOccurs>
    					<value>10</value>
    					<validation>
    						<severity>warning</severity>
    						<message xml:lang="en-US">Too much products for this catalog.</message>
    						<message xml:lang="fr-FR">Ce catalogue a trop de produits.</message>
    					</validation>
    				</maxOccurs>
    			</osd:association>
    		</xs:appinfo>
    	</xs:annotation>
    </xs:element>

## Linked fields

### Overview

Linked fields provide the ability to simulate a multi-table view by aggregating the fields of a main table with some fields of another table over an existing relationship. It allows an easy model-driven integration of some fields from records that are referred by other ones using relationships.

##### See also

- `SchemaLinkedField`

Following relationships can be traversed:

- Foreign key constraints.

- Associations 'By foreign key'.

Important: these relationships must be "single valued relationships". That is, a record of the table that defines the relationship must refer to only one record in the target table of the relationship.

In details:

- A foreign key is considered as a single valued relationship if the foreign key field defines a maxOccurs equal to 1.

- An association by foreign key is considered as a single valued relationship if the referred foreign key field is the unique primary key field of the target table or if an uniqueness constraint is defined on this foreign key field.

##### Note

A linked field inherits some properties from its target field (foreign key constraint, enumeration, value labelling, search strategies, search mode, formatting).

### Declaration

A linked field, which is an element with minOccurs = 0 and maxOccurs = 0, is declared by adding the following annotation:

    	<xs:element name="catalog_ref_label" minOccurs="0" maxOccurs="0" type="xs:string">
    		<xs:annotation>
    			<xs:appinfo>
    				<osd:function linkedField="../catalog_ref/catalogLabel"/>
    			</xs:appinfo>
    		</xs:annotation>
    	</xs:element>

Attribute linkedField defined in element osd:function defines a path composed of steps which refer to a single-valued relationship in the container table and of steps to a field in the target table of the relationship.

Important:

- If the path is absolute (starts with a "/") then it will be resolved from the container table node.

- If the path is relative then it will be resolved from the current field.

In the context of the product catalog data model defined previously, the field catalog_ref_label is added in the Products table. The first step catalog_ref refers to the foreign key that indicates that a product belongs to a catalog. The last step catalogLabel refers to the label of the referred catalog. This field belongs to the Catalog table that is the target table of the foreign key constraint.

Restrictions:

- Currently, linked fields only allow to target one level of single valued relationships. As a consequence:

  - The single-valued relationship cannot be defined by another linked field.

  - A linked field cannot target another linked field.

- A linked field must define properties minOccurs and maxOccurs. equal to 0.

- A linked field must define a data type that is compatible with the one of the target field.

- A linked field cannot be a part of the primary key of the container table.

- A linked field must target a terminal field.

- A linked field cannot target an aggregated list or a field under an aggregated list.

- A linked field cannot refer to a single-valued relationship that is also a linked field.

- Constraints should not be defined on a linked field. If constraints are declared on a linked field, a warning message will be thrown and the declared constraints will be ignored.

- For a linked field, the property `osd:disableValidation` is always considered as `true` and cannot be overwritten.

Documentation > Developer Guide > Data model