(from v2.12.0)

Note
This target supports ldproxy versions 3.1.0 and upwards.

1. Overview

2. Schema Conversion Rules

The following subsections describe a number of conversion rules, which define how the contents of application schemas are converted to ldproxy configuration files.

Note
An encoding rule consists of a set of conversion rules – as required by a community. The Encoding Rules section describes how encoding rules can be defined.

2.1. Configuration file templates

The ldproxy target creates the following folder structure in the output directory:

  • data

    • store

      • entities

        • codelists (only if a codelist or enumeration is actually encoded)

        • providers

        • services

The target output will be written to these folders.

Caution
Make sure that when copying the output files, you end up with this folder structure! Do not, for example, forget to create the 'entities' folder by just copying the 'codelists', 'providers', and 'services' folders to a 'store' folder. Otherwise, ldproxy will just assume that the store is empty.

Some configuration data can simply be copied using template files. Table 1 lists the templates that the target uses, with information about:

  • The name of the ShapeChange target parameter with which the path to the template file can be provided.

  • If applicable: The default template location, i.e. the path that will be used by the target if no path is given via the target parameter.

  • If applicable: The path within the output folder to which the template file will be copied.

  • A description of the template file.

Table 1. Configuration file templates
target parameter name default template location output folder description

cfgTemplatePath

https://shapechange.net/resources/templates/ldproxy2/cfgTemplate.yml

data/cfg.yml

The cfg.yml contains the global configuration for all APIs in the intended API deployment.

serviceConfigTemplatePath

none - Nevertheless, an example is provided at https://shapechange.net/resources/templates/ldproxy2/serviceConfigTemplate.yml

none - will be integrated into the service configuration

The object defined by this template file will be patched into the service configuration. This is useful to, for example, define service metadata.

2.2. Documentation

With rule-ldp2-all-documentation, descriptive information of application schema elements (for ldproxy that primarily means classes and their properties) can be encoded within the ldproxy configuration, more specifically: in label and description members of type definitions.

Note

Descriptive information of a model element in ShapeChange, i.e. properties (attributes and association roles), classes, and packages, includes the pieces of information, called descriptors, that are documented here.

A model element can have all, a subset, or none of these descriptors.

Typically, a community has a preferred way to model and encode this information. For example, one community may want to encode just the description of a property via the "description" member in the provider configuration, while another may prefer to encode the values of multiple descriptors of the property within the "description" member. Therefore, templates are used to define the (combination of) descriptor(s) that shall be used as value for label and description members:

  • target parameter labelTemplate:

    • default value: [[alias]]

    • explanation: The template for the label member generated for a type definition. The patterns "[[descriptor]]" will be replaced by the value of the descriptor, or the value of parameter descriptorNoValue, if the descriptor has no value for the model element.

  • target parameter descriptionTemplate:

    • default value: [[definition]]

    • explanation: The template for the description member generated for a type definition. The patterns "[[descriptor]]" will be replaced by the value of the descriptor, or the value of parameter descriptorNoValue, if the descriptor has no value for the model element.

  • target parameter descriptorNoValue:

    • default value: "" (i.e., the empty string)

    • explanation: If a descriptor is used in a label or description template, but has no value, then the value of this parameter will be used instead.

Note
If the resulting value for label or description is blank, i.e. the empty string or only whitespace, then the value will not be encoded.

2.3. Schema Packages

Schema packages have the stereotype <<applicationSchema>>, <<schema>>, or an alias (e.g. using a specific language, like <<anwendungsschema>>). An <<applicationSchema>> package represents an application schema according to ISO 19109. The stereotype <<schema>> has been introduced for packages that should be treated like application schemas, but do not contain feature types. Such schemas are compliant to ISO 19103; examples are ISO 191xx schemas.

This ldproxy target is a so-called "ShapeChange Single Target", i.e. it converts all schemas selected for processing in one go, rather than handling each of these schemas separately.

The target creates a single provider configuration (in folder data/store/entities/providers) as well as a single service configuration file (in folder data/store/entities/services). The names of these files are given by the name of the main schema, in all lower case, and non-word characters replaced by '_'. The resulting name is also used as the id within these files. The encoding details for each of the two configuration files are documented in sections Provider Configuration and Service Configuration.

Note
If a single API (provider and service configuration) shall be created for each schema, set the schema selection parameter appropriately. If multiple schemas need to be processed, and each shall result in a different API, then either run ShapeChange multiple times (updating the schema selection parameters each time) or define multiple ldproxy targets (each selecting a different schema for processing).

2.3.1. Provider Configuration

The following information items are added to the provider configuration file:

  • id: the provider name (derived from the main schema, as defined in section Schema Packages)

  • createdAt and lastModified: receive the integer value for an automatically generated unix time stamp (fixed for UnitTests)

  • entityStorageVersion: 2

  • providerType: FEATURE

  • featureProviderType: SQL

  • connectionInfo:

    • dialect: PGIS

      • NOTE: A future enhancement of this target may support GeoPackage (dialect: GPKG).

    • database: FIXME

    • host: FIXME

    • user: FIXME

    • password: FIXME-base64-encoded

    • schemas: "public" - and, if rule-ldp2-all-schemas is active, all values from tags sqlSchema on the package elements of all processed schemas

      • NOTE: This corresponds to the database schema definition mechanism supported by the SqlDdl target in rule-sql-all-schemas.

  • sourcePathDefaults:

    • primaryKey: value of target parameter primaryKeyColumn; default: id

      • NOTE: Corresponds to SqlDdl target parameter idColumnName

    • sortKey: same as primaryKey

  • queryGeneration:

    • computeNumberMatched: true

  • nativeCrs:

    • code: value of target parameter srid; default is 4326

      • NOTE: The SqlDdl target has a similar parameter.

    • forceAxisOrder: value of target parameter forceAxisOrder; default is NONE

  • nativeTimeZone: value of target parameter nativeTimeZone; default: NONE

    • NOTE: The time-zone ID is given as a string like 'Europe/Paris'. Internally, parsing is achieved using the Java ZoneId class and its static of(String zoneId) method. The system default time-zone ID is determined via the static systemDefault() method. For further information about the allowed formats of the time-zone ID, consult the documentation of the Java ZoneId class and the two methods.

  • types: will be populated as described in section Types

  • fragments: will be generated if target parameter enableFragments is set to true. For further details, see section Inheritance and Specialization.

Note
Members of the provider configuration, whose value is equal to the default value for that member defined by ldproxy, may not actually be written to the provider configuration file created by the target.
Note
The deployment-specific values of the connectionInfo member - i.e. the database, host, user, and password - should either be set via environment variables, or via an overriding configuration file. The override would be placed in folder store/overrides/providers and carry the same name as the provider configuration whose connection infos shall be overridden.

2.3.2. Service Configuration

The following information items are added to the service configuration file:

  • id: the service name (derived from the main schema, as defined in section Schema Packages)

  • createdAt and lastModified: receive the integer value for an automatically generated unix time stamp (fixed for UnitTests)

  • entityStorageVersion: 2

  • label: value of target parameter serviceLabel; default is 'FIXME'

  • description: value of target parameter serviceDescription; default is 'FIXME'

  • serviceType: OGC_API

  • metadata: can be provided - in form of a template - via target parameter serviceConfigTemplatePath; metadata information for the actual API is typically not included in the model, therefore the target uses information provided via a separate template file

  • api: can be provided - in form of a template - via target parameter serviceConfigTemplatePath; information about the modules implemented by the actual API is typically not included in the model, therefore the target uses information provided via a separate template file

  • collections: will be populated as described in section Types.

  • If target parameter enableGmlOutput is 'true' (default being 'false'), then API building blocks as described in subsection Features - GML are added to the service configuration.

Note
Members of the service configuration, whose value is equal to the default value for that member defined by ldproxy, may not actually be written to the service configuration file created by the target.
2.3.2.1. Features - GML

Version 3.3.0 of ldproxy supports encoding data as GML. The documentation of ldproxy building block Features - GML describes relevant configuration items. By setting target parameter enableFeaturesGml to 'true', ShapeChange will add ldproxy building block Features - GML to the service configuration as enabled.

Note
The initial name of the target parameter was enableGmlOutput. For backwards compatibility of existing ShapeChange configurations, the old parameter name is supported as an alias for enableFeaturesGml.

The target thereby needs to know how application schema elements shall be represented in XML. In other words, it needs to know how the desired XML encoding looks like. This information can be generated by the XmlSchema target, if parameter writeXmlEncodingInfos is set to 'true' there. The format of the XML encoding infos generated by the XmlSchema target is documented here. The XML encoding infos need to be placed within the advancedProcessConfigurations element of the ldproxy target configuration. The ShapeChange workflow may thus need to be run twice - first, to generate XML schemas and their XML encoding infos, and then to derive the ldproxy configuration files, using the XML encoding infos in the configuration of the ldproxy target. The following example shows how this is done:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<Target class="de.interactive_instruments.ShapeChange.Target.Ldproxy2.Ldproxy2Target" mode="enabled" inputs="TRF_END">
  <advancedProcessConfigurations>
    <XmlEncodingInfos>
      <modelElementEncodings>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="FeatureTypeA" xmlName="AbstractFeatureTypeA" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="FeatureTypeA::attMeasure" xmlName="attMeasure" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="FeatureTypeA::ftAtoTA" xmlName="ftAtoTA" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="FeatureTypeA::geom" xmlName="geom" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="DataTypeA" xmlName="DataTypeA" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="DataTypeA::att1" xmlName="att1" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="DataTypeA::att2" xmlAttribute="true" xmlName="att2" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="TypeA" xmlName="TypeA" xmlNamespace="http://shapechange.net/test/a"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema A" modelElementName="TypeA::attCodelistA" xmlName="attCodelistA" xmlNamespace="http://shapechange.net/test/a"/>
      </modelElementEncodings>
      <namespaces>
        <XmlNamespace ns="http://shapechange.net/test/a" nsabr="a"/>
      </namespaces>
    </XmlEncodingInfos>
    <XmlEncodingInfos>
      <modelElementEncodings>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema B" modelElementName="FeatureTypeB" xmlName="FeatureTypeB" xmlNamespace="http://shapechange.net/test/b"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema B" modelElementName="FeatureTypeB::att1" xmlAttribute="true" xmlName="att1" xmlNamespace="http://shapechange.net/test/b"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema B" modelElementName="FeatureTypeB::att2" xmlName="att2" xmlNamespace="http://shapechange.net/test/b"/>
        <ModelElementXmlEncoding applicationSchemaName="Cross Schema B" modelElementName="FeatureTypeB::att3" xmlName="att3" xmlNamespace="http://shapechange.net/test/b"/>
      </modelElementEncodings>
      <namespaces>
        <XmlNamespace ns="http://shapechange.net/test/b" nsabr="b"/>
      </namespaces>
    </XmlEncodingInfos>
  </advancedProcessConfigurations>
  <targetParameter name="outputDirectory" value="results/ldproxy2/gmlOutput"/>
  <!-- ... other configuration items omitted for brevity ... -->
</Target>

The ldproxy target attempts to identify the XML encoding of a particular model element as follows:

  • First, it is necessary to understand the concept that a schema which has been transformed can be significantly different to the one from which the XML schema has been derived. The schema and class to which a property belonged in the input model can be changed by flattening inheritance and flattening complex types. The same applies to the property name - it may also be changed by a transformation. If inheritance or complex types have been flattened, the original class, schema, as well as property name can be documented in tagged values originalSchemaName, originalInClassName, and originalPropertyName. For further details as to which properties exactly are tagged this way, see the documentation of the Tagged Value transformation rule rule-trf-taggedValue-createOriginalSchemaInformationTags, as well as the Flattener transformation rules rule-trf-cls-flatten-inheritance and rule-trf-prop-flatten-types. If these tags are set, they are used when looking up the XML namespace and XML name of a model element. Otherwise, the name of the model element, in case of a property also the class that owns it, as well as the schema are taken directly from the model.

  • For a model element - classes and properties -, the XML namespace in which it is XML encoded needs to be known. If no ModelElementXmlEncoding element defines that namespace, then ShapeChange uses the target namespace of the schema the model element belongs to in the model. The target namespace is either defined by tag targetNamespace on the schema package, or via PackageInfo elements in the ShapeChange configuration. If no namespace can be identified this way, either, then a value of 'fixme' with a counter is assigned to the schema package.

  • The XML namespace abbreviation to use for the XML namespace is determined in a similar manner. First, namespace definitions in the XML encoding infos are checked. If they do not contain a definition for the namespace, the model is checked (tag xmlns of the schema package, and subsequently PackageInfo elements of the ShapeChange configuration). If all else fails, a value of 'fixme' plus a counter is assigned.

  • The XML name of the model element is looked up in the XML encoding infos, taking into account tags originalSchemaName, originalInClassName, and originalPropertyName, if set. If the XML name was not found this way, the model element name is used - unless, for a property, tag originalPropertyName has a value; in that case, that value is used.

The target creates a general GML API building block in the service configuration. It contains the following members:

  • The XML namespaces and their abbreviations of model elements that are processed by the target are encoded within the applicationNamespaces member.

  • The XML namespace abbreviation of the main application schema is assigned as value of the defaultNamespace member.

    • NOTE: The ldproxy target can process multiple application schemas at once, and the result are single provider and service configuration files (among others, like codelist definitions). Here, the mainAppSchema (input) parameter and concept comes into play. If multiple schemas are processed, the one that shall be used as the default namespace is defined by the mainAppSchema input parameter. If the parameter is not set, ShapeChange acts as follows: if there is only a single schema to process, it is selected as main schema. Otherwise, a warning is issued and the first schema that is processed by the target is chosen as main schema.

  • The schemaLocations member is populated as follows:

    • For the XML namespace of the main application schema, the schema location from the XML encoding infos is used. If no location can be found this way, it is assumed that the XML schema for this namespace shall be hosted by ldproxy itself. In that case, API building block RESOURCES is enabled, and the schema location value will be {{serviceUrl}}/resources/ + the value of tag xsdDocument of the main application schema. Example: {{serviceUrl}}/resources/myschema.xsd

    • For all other XML namespaces that apply to the model elements processed by the ldproxy target, if the namespace definitions in the XML encoding infos define schema locations, then they are added.

  • The objectTypeNamespaces member is populated with the names of the object types which occur in the provider configuration AND whose XML namespace is different to the default namespace. The name of such an object type is used as key, while the XML namespace abbreviation is used as value.

  • If target parameter gmlIdPrefix is set, its value is used as value of the gmlIdPrefix member.

  • If target parameter gmlSfLevel is set (to one of the allowed values 0, 1, and 2), its value is set as the value of the gmlSfLevel member.

  • Likewise, if target parameter featureCollectionElementName is set, its value is used in the corresponding member. The same applies for the value of target parameters featureMemberElementName and supportsStandardResponseParameters.

For each collection, the target generates a GML building block entry in the service configuration, if at least one of the following situations applies:

  • If the XML name or XML namespace of a property (on any level within the type definition) is different to the name used in the provider configuration, or the default XML namespace, a rename transformation is applied to that property, using the XML QName as value (the XML namespace prefix is omitted, if the XML namespace is the same as the default namespace).

  • If a property is encoded as an XML attribute, the property path is added as value to the xmlAttributes member.

Example (from one of the ShapeChange unit tests):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
collections:
  featuretypeb:
    id: featuretypeb
    label: featuretypeb
    enabled: true
    api:
    - buildingBlock: GML
      transformations:
        att2.att1:
        - rename: a:att1
        att2.att2:
        - rename: a:att2
      conformance: NONE
      xmlAttributes:
      - att1
      - att2.att2
2.3.2.2. Features - GeoJSON

By setting target parameter enableFeaturesGeoJson to 'true', ShapeChange will add ldproxy building block Features - GeoJSON to the service configuration as enabled.

Currently, specific configuration items for this building block are added through the Conversion of generic value types. In the future, generation of additional configuration items for this building block can be supported.

2.3.2.3. Features - JSON-FG

By setting target parameter enableFeaturesJsonFg to 'true', ShapeChange will add ldproxy building block Features - JSON-FG to the service configuration as enabled.

Currently, specific configuration items for this building block are added through the Conversion of generic value types. In the future, generation of additional configuration items for this building block can be supported.

2.3.2.4. Queryables

If the main application schema matches rule-ldp2-all-queryables, the target creates a QUERYABLES building block in the service configuration. It just contains the member enabled: true.

For each collection, whose represented type matches rule-ldp2-all-queryables, the target checks which, if any, of the properties have a name - current or original - equal to one of the names provided by target parameter queryables (the parameter value is a comma-separated list of property names; no default value is defined). If at least one such property was found, the target creates a queryables member in the QUERYABLES building block in the service configuration of the collection (adding that building block if necessary), with:

  • member included and an array of the names of all queryable properties. If a queryable association role does NOT match rule-ldp2-all-linkObjectAsFeatureRef, then .title is added to the role name (meaning that queries will be performed on the title-value of the link object that is encoded for an association role).

  • member pathSeparator and value DOT.

Note
The differentiation between 'current' and 'original' property name is important when the ldproxy target shall encode a model which has been flattened (flattening inheritance and/or complex types). When inheritance or complex types are flattened, property names can be modified. When this happens (in the mentioned flattening cases), the original property name is documented in tagged value originalPropertyName. The ldproxy target checks this tag when matching properties of a value type against the configured list of queryables.
Note
The definition of queryable properties using the global target configuration parameter queryables can be enhanced in the future. For example, it would be possible to introduce a specific tag, to be set on a type, which would provide the names of queryable properties of that type.

Example (from one of the ShapeChange unit tests):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
collections:
  featuretype:
    id: featuretype
    label: featuretype
    enabled: true
    api:
    - buildingBlock: QUERYABLES
      included:
      - attDate
      - attInt
      - attPoint
      - roleFTtoT_Subtype.title
      - roleFTtoT_Type.title
      pathSeparator: DOT

2.4. Types

2.4.1. Mappings

Application schemas typically use types from other schemas, for example the types defined by ISO 19103 and ISO 19107. External types can be used as value types of properties, and as supertypes for types defined in the application schema that is being converted.

Whenever an external type is used, its implementation details are needed. An external type must be implemented as one of the types supported by ldproxy, or as a link / feature reference. The target type of a map entry must therefore be one of:

  • FLOAT, INTEGER, STRING, BOOLEAN, DATETIME and DATE

    • Relevant map entry parameter(s): initialValueEncoding (optional, currently only used for mapping of the conceptual type 'Boolean')

  • GEOMETRY

    • Relevant map entry parameter(s): geometryInfos (required)

  • LINK

    • NOTE: Types that are mapped to links - more specifically, link objects - are considered to be available as an external resource. Linking to such objects can be useful for integration and re-use of external APIs.

    • Relevant map entry parameter(s): linkInfos (required)

Note
The semantic validation (a pre-processing step executed by ShapeChange upon loading the configuration) of the ldproxy target configuration will ensure that map entries contain required map entry parameters.

Note that while a type mapping typically applies to external types, it can also be applied to a type from the application schema. For example, some identifier datatype (e.g. called 'GUID') could be defined within the application schema, but be implemented within the database and thus also in the resulting ldproxy configuration as a STRING.

A map entry for the ldproxy target has the following structure:

  • @type (required): The unqualified UML type/class name to be mapped. Should be unique within the model (if it is not unique, this can lead to unexpected results).

  • @rule (required): The encoding rule to which this mapping applies. May be "*" to indicate that the mapping applies to all encoding rules.

  • @targetType (required): One of FLOAT, INTEGER, STRING, BOOLEAN, DATETIME, DATE, GEOMETRY, or LINK.

  • @param (optional): Defines one or more parameters for the mapping. If no parameter is provided (leaving the 'param' attribute empty) then the map entry contains a straightforward mapping, usually to a simple type. Each parameter has a name. A list of parameters is separated by commas. Each parameter can also have characteristics defined for it, providing even further information for the conversion. Characteristics for a parameter are provided within curly braces. A characteristic usually is provided by a key-value pair, with the key being the identification of the characteristic.

    • Parameter initialValueEncoding: Defines how initial values of properties whose value type is mapped by the map entry should be encoded. Currently only relevant for mapping of type Boolean to some ldproxy type.

      • Characteristic: true (optional): Specifies the value to represent the Boolean value true in the mapping that the parameter applies to. Only relevant for mapping of type Boolean. Default is true.

      • Characteristic: false (optional): Specifies the value to represent the Boolean value false in the mapping that the parameter applies to. Only relevant for mapping of type Boolean. Default is false.

      • NOTE: Mappings of initial values for type Boolean are especially important if boolean values are represented in the database using a non-boolean datatype. For example, the value true could be represented by integer 1, while false would be represented by 0.

    • Parameter geometryInfos: Indicates that the map entry contains a mapping for a geometry type (specifically from ISO 19107), and provides further information via characteristics.

      • Characteristic geometryType (required): Specify the actual geometry type, using one of the geometry types supported by ldproxy: POINT, MULTI_POINT, LINE_STRING, MULTI_LINE_STRING, POLYGON, MULTI_POLYGON, GEOMETRY_COLLECTION, ANY

    • Parameter linkInfos: provides information for constructing a link- object.

      • Characteristic: urlTemplate (required): Defines a template for constructing the URL to an actual property value, given an identifier value, which is represented in the template using placeholder (value). The placeholder (serviceUrl) can be used as well. It will be replaced by an ldproxy deployment with its base URL.

        • NOTE: Due to an implementation restriction in the parsing process of map entry parameters and their characteristics, braces are not directly allowed within the value of the urlTemplate characteristic. The target will automatically replace the parentheses ('(' and ')') around the placeholders with braces ('{' and '}') when writing them in the ldproxy configuration.

      • Characteristic: tableName (optional): Name of the database table that represents the mapped type. Is used to construct source paths, for cases in which a property with the mapped type as value type has a maximum multiplicity greater than one (which typically results in the use of an associative table, in which the mapped type must be represented with a foreign key field). The characteristic reflects the map entry parameter table of the SQL DDL target. If the database schema has been created with such a mapping, then a corresponding mapping is likely required for the ldproxy target.

      • Characteristic: representedCategory (optional): The value identifies the category of the conceptual type that is identified by the map entry. Recognized values are: datatype and codelist. Primarily required for correctly creating source paths.

2.4.2. Abstractness

Abstract types are not converted to individual provider type definitions. However, if target parameter enableFragments is set to true, then abstract types will be converted to fragment definitions.

2.4.3. Inheritance and Specialization

Since v2.14.0, conversion of inheritance relationships is supported by the target, if target parameter enableFragments is set to true.

Note
Before v2.14.0, such relationships had to be transformed, before executing the ldproxy target (e.g. use the Flattener transformation to flatten inheritance).

With fragments enabled, the provider configuration contains type definitions as well as fragment definitions. The fragment definitions thereby define the structure of a type in detail: object type, documentation, properties, etc. However, source path information is only contained for cases in which the path is a simple column name within the source table of the current context (e.g., a type definition). For other cases, the source path is encoded within the type definition.

If a type has supertypes, then the fragment definition of the type merges the fragment definitions of these supertypes, as well as the schema of the properties directly owned by the type. If a class only has a single supertype, then a direct schema reference (to the fragment definition of the supertype) is used. If the class has multiple supertypes, the merge keyword is used to encode the necessary references.

Warning

Multiple inheritance is only supported if no (direct or indirect) supertype of the class uses multiple inheritance! This is currently a restriction of ldproxy regarding the merge keyword.

The merge keyword results in a shallow merge, where property override applies. That reflects the property override in UML, i.e., a property defined in a subclass overrides the definition of a property with same name that is defined in a (direct or indirect) superclass. Be aware, though, that the schema reference results in a deep merge. Property overrides in the application schema may lead to unexpected results there.

In case of multiple inheritance, the merge items are encoded in a way that reflects the order in which the XML Schema target encodes supertype properties (also taking into account mixin encoding). This is an important aspect when Features - GML shall be supported by the resulting ldproxy configuration.

A type definition references the according fragment definition via a schema member. The type definition encodes the source path to identify the objects of that type. It also provides source paths for all properties directly owned or inherited by the type, for non-simple cases (as described before, simple cases are encoded in the fragment definition). Furthermore, if the value(s) of a property can be encoded in the database in multiple ways - for example because of multiplicity being flattened (like a property with max multiplicity 2), and the property values thus being SQL encoded by multiple separate columns, or because the property value type has subtypes, and each subtype is SQL encoded in a separate table - the property is typically encoded (in the type definition) as a FEATURE_REF using the ldproxy keyword concat or coalesce. The former is used if the maximum multiplicity of the property is greater than one, the latter if it is equal to one. Further details on the encoding of a FEATURE_REF are given here.

Note
The following example is from one of the ShapeChange unit tests. The ShapeChange configuration and results of that test are available here, while the model is available here. The example only shows an extract of the whole unit test.
ldp2 inheritance example
Figure 1. Example schema with inheritance structures, to illustrate fragment encoding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
collections:
  t8_class1:
    sourcePath: /t8_class1
    type: OBJECT
    label: T8_Class1
    properties:
      pMixA2Mult:
        sourcePath: "[_id=t8_class1_id]t8_class1_pmixa2mult/pmixa2mult"
        type: VALUE_ARRAY
        valueType: INTEGER
      attC1Mult:
        sourcePath: "[_id=t8_class1_id]t8_class1_attc1mult/attc1mult"
        type: VALUE_ARRAY
        valueType: INTEGER
      role1to2:
        sourcePath: "[_id=t8_class1_id]t8_class1_role1to2_t8_class2sub/t8_class2sub_id"
        type: FEATURE_REF_ARRAY
        valueType: INTEGER
        refType: t8_class2sub
    schema: '#/fragments/t8_class1'
  t8_class1sub:
    sourcePath: /t8_class1sub
    type: OBJECT
    label: T8_Class1Sub
    properties:
      pMixA2Mult:
        sourcePath: "[_id=t8_class1sub_id]t8_class1sub_pmixa2mult/pmixa2mult"
        type: VALUE_ARRAY
        valueType: INTEGER
      attC1Mult:
        sourcePath: "[_id=t8_class1sub_id]t8_class1sub_attc1mult/attc1mult"
        type: VALUE_ARRAY
        valueType: INTEGER
      role1to2:
        sourcePath: "[_id=t8_class1sub_id]t8_class1sub_role1to2_t8_class2sub/t8_class2sub_id"
        type: FEATURE_REF_ARRAY
        valueType: INTEGER
        refType: t8_class2sub
      attC1SubMult:
        sourcePath: "[_id=t8_class1sub_id]t8_class1sub_attc1submult/attc1submult"
        type: VALUE_ARRAY
        valueType: STRING
    schema: '#/fragments/t8_class1sub'
  t8_class2sub:
    sourcePath: /t8_class2sub
    type: OBJECT
    label: T8_Class2Sub
    properties:
      role2to1:
        type: FEATURE_REF_ARRAY
        concat:
        - sourcePath: "[_id=t8_class2sub_id]t8_class1_role1to2_t8_class2sub/t8_class1_id"
          type: FEATURE_REF_ARRAY
          valueType: INTEGER
          refType: t8_class1
        - sourcePath: "[_id=t8_class2sub_id]t8_class1sub_role1to2_t8_class2sub/t8_class1sub_id"
          type: FEATURE_REF_ARRAY
          valueType: INTEGER
          refType: t8_class1sub
    schema: '#/fragments/t8_class2sub'
fragments:
  t8_class1:
    type: OBJECT
    objectType: T8_Class1
    label: T8_Class1
    properties:
      oid:
        sourcePath: _id
        type: INTEGER
        role: ID
      attC1:
        sourcePath: attc1
        type: INTEGER
        label: attC1
        constraints:
          required: true
      attC1Mult:
        type: VALUE_ARRAY
        valueType: INTEGER
        label: attC1Mult
        constraints:
          required: true
          minOccurrence: 1
      role1to2:
        type: FEATURE_REF_ARRAY
        label: role1to2
        constraints:
          required: true
          minOccurrence: 1
    schema: '#/fragments/t8_mixin_b'
  t8_class1sub:
    type: OBJECT
    objectType: T8_Class1Sub
    label: T8_Class1Sub
    merge:
    - schema: '#/fragments/t8_class1'
    - schema: '#/fragments/t8_mixin_c'
    - schema: '#/fragments/t8_mixin_d'
    - properties:
        attC1Sub:
          sourcePath: attc1sub
          type: STRING
          label: attC1Sub
          constraints:
            required: true
        attC1SubMult:
          type: VALUE_ARRAY
          valueType: STRING
          label: attC1SubMult
          constraints:
            required: true
            minOccurrence: 1
  t8_class2:
    type: OBJECT
    objectType: T8_Class2
    label: T8_Class2
    properties:
      oid:
        sourcePath: _id
        type: INTEGER
        role: ID
      attC2:
        sourcePath: attc2
        type: FLOAT
        label: attC2
        constraints:
          required: true
      role2to1:
        type: FEATURE_REF_ARRAY
        label: role2to1
        constraints:
          minOccurrence: 0
  t8_class2sub:
    type: OBJECT
    objectType: T8_Class2Sub
    label: T8_Class2Sub
    properties:
      attC2Sub:
        sourcePath: attc2sub
        type: BOOLEAN
        label: attC2Sub
        constraints:
          required: true
    schema: '#/fragments/t8_class2'
  t8_mixin_a:
    type: OBJECT
    objectType: T8_Mixin_A
    label: T8_Mixin_A
    properties:
      pMixA1:
        sourcePath: pmixa1
        type: INTEGER
        label: pMixA1
        constraints:
          required: true
      pMixA2:
        sourcePath: pmixa2
        type: BOOLEAN
        label: pMixA2
        constraints:
          required: true
      pMixA2Mult:
        type: VALUE_ARRAY
        valueType: INTEGER
        label: pMixA2Mult
        constraints:
          required: true
          minOccurrence: 1
  t8_mixin_b:
    type: OBJECT
    objectType: T8_Mixin_B
    label: T8_Mixin_B
    properties:
      pMixB:
        sourcePath: pmixb
        type: FLOAT
        label: pMixB
        constraints:
          required: true
    schema: '#/fragments/t8_mixin_a'
  t8_mixin_c:
    type: OBJECT
    objectType: T8_Mixin_C
    label: T8_Mixin_C
    properties:
      pMixC:
        sourcePath: pmixc
        type: STRING
        label: pMixC
        constraints:
          required: true
  t8_mixin_d:
    type: OBJECT
    objectType: T8_Mixin_D
    label: T8_Mixin_D
    properties:
      pMixD:
        sourcePath: pmixd
        type: INTEGER
        label: pMixD
        constraints:
          required: true

The representation of certain model elements in the underlying database can vary significantly. It is therefore highly recommended to provide the ldproxy target with SQL encoding infos (available since v2.14.0). They can be produced by the SQL DDL target. The encoding infos can be provided via the advancedProcessConfigurations element of the ldproxy target configuration. The following example shows how that can be done:

1
2
3
4
<Target class="de.interactive_instruments.ShapeChange.Target.Ldproxy2.Ldproxy2Target" mode="enabled" inputs="TRF_END">
  <advancedProcessConfigurations>
    <xi:include href="./config/SqlEncodingInfos.xml"/>
    <!-- ... -->
Note
The ShapeChange workflow may need to be run twice - first, to generate the database schema and the SQL encoding infos, and then to derive the ldproxy configuration files, using the SQL encoding infos in the configuration of the ldproxy target.
Note
The advancedProcessConfigurations element may contain multiple includes, for example one for the SQL encoding infos, and one for the XML encoding infos.
Caution
Only provide SQL encoding infos that match the underlying database schema! If additional SQL encoding infos are provided for schema elements, with tables and source paths that simply do not exist in the database schema, the resulting ldproxy configuration may be incorrect. Concat or coalesce members may have been created erroneously. A use case where this is important is profiling: if multiple profiles are created for the same application schema, and an individual database schema is created for each profile, then do NOT configure a single ldproxy target with the according profile models as inputs, and the SQL encoding info XML files from all profiles included in that target configuration! Instead, configure one ldproxy target for each profile - only including the SQL encoding infos generated for the corresponding database schema.

2.4.4. Database Table Name

Whenever a type from the application schema is encoded within an ldproxy provider configuration, the name of the database table that represents that type is required (especially for constructing source paths).

The name of the database table is determined as follows:

  • If SQL encoding infos are configured, the target looks up the table name there.

  • Otherwise, the target constructs a table name itself:

    • Basically, the type name is used as table name.

    • A suffix can be added to the table name, depending upon the conversion context:

      • If the name is used as column name within an associative table (typically for n-to-m relationships), which does NOT represent a reflexive relationship, then the value of target parameter associativeTableColumnSuffix (with default value being the value of target parameter primaryKeyColumn) is used as suffix.

        • NOTE: This supports behavior of the SqlDdl target regarding the construction of associative tables.

    • In addition, the table name established so far is converted to lower case (using the english locale).

    • Finally, the table name is restricted to a substring (starting at the beginning of the name) whose length does not exceed the value of target parameter maxNameLength (whose default value is 63 [characters]).

Note

In the future, conversion rules can be defined to modify the default naming behavior.

2.4.5. Feature and Object Type

In the conceptual model, feature and object types represent objects that have identity. That differentiates these types from, for example, data types. Other than that, feature and object types - in the following called types with identity - are encoded as top-level type (and potentially also fragment) definitions within the provider configuration as well as collection definitions in the service configuration.

Note
A feature type typically has stereotype <<featuretype>>, while an object type has stereotype <<type>>, <<interface>>, or no stereotype.
Note
If a map entry is defined for the type, it is not encoded in the provider configuration.
Note
A future enhancement of the ldproxy target could introduce mechanisms for suppressing the global type definition within a provider configuration for a type with identity, instead inlining this definition whenever the type is used as property value type. Examples would be BuildingPart (which could be inlined into Building), as well as subtypes of INSPIRE AddressComponent (which could be inlined into Address).
2.4.5.1. Provider Type Definition

The name of the definition is the class name. The name can be formatted, as defined by target parameter collectionIdFormat (default value is 'lowerCase'). Supported parameter values are:

  • none - no formatting is applied; can be useful for the Coretable Approach.

  • lowerCase - The name is converted to lower case, using the English locale.

Note
ISO 19109 requires class names to be unique within the scope of a single application schema. Although not recommended, different schemas may define types with same name. The ldproxy target will log an error if it encounters multiple classes (from the schemas selected for processing) that have equal name (ignoring case) and which shall be encoded by the target.

The following information items are encoded within the provider configuration:

  • type: OBJECT

  • objectType: original name of the type (taken from tagged value originalClassName, if present, otherwise it is the class name as found in the - potentially transformed and thus altered - model)

  • sourcePath: "/" + {table_name}

  • label: value as derived using the labelTemplate (see the documentation section for further details)

  • description: value as derived using the descriptionTemplate (see the documentation section for further details)

  • properties: as documented in section Properties

Note
If target parameter enableFragments is set to true, type AND fragment definitions are encoded. For further details, see section Provider Configuration.
2.4.5.2. Service Collection Definition

The name of the collection definition is the class name, formatted according to target parameter [collectionIdFormat]. It is therefore equal to the name of the provider type definition.

The following information items are encoded for the collection definition within the service configuration:

  • id: the collection name

  • label: same as id

  • api:

    • -buildingBlock: FEATURES_HTML

      • featureTitleTemplate: value of tag ldpFeatureTitleTemplate on the class; no default is defined. The value must define a template with one or more property names from the ldproxy configuration (e.g. {{title}}).

      • transformations: an object with members depending upon the conversion of the type properties and their value types (see sections Enumeration and Code List and Features HTML API-Module, Property Transformations)

Note
Currently, specific API conversion behavior is only defined for the Features HTML API-Module. In the future, the definition of queryables and sortables can be added.
2.4.5.3. Identifier member

The conceptual model of a type with identity often does not contain a property whose value is used by applications to identify objects of that type. Instead, the according information is added or defined in platform specific encodings. For example, a GML application schema offers the gml:id attribute as well as the gml:identifier element to encode identifying information.

In ldproxy, each provider type definition must have a property that functions as object identifier.

  • If rule-ldp2-cls-identifierStereotype applies to the type, and the type - or one of its supertypes - has an <<identifier>> property, then that property will be encoded as such an object identifier.

    • NOTE: If the maximum multiplicity of an <<identifier>> attribute is greater than 1, an error will be logged. Processing will continue, assuming a maximum multiplicity of 1 for the attribute.

  • Otherwise, an identifier member is explicitly encoded. The member name is given by target parameter objectIdentifierName (default: "oid"). The value of the sourcePath is the value of target parameter primaryKeyColumn with type INTEGER.

The object identifier property will receive member role with value ID.

Note
If a type has multiple identifier properties (directly owned and/or inherited), none of them is used as object identifier (because no informed choice can be made). An error will be logged. The target will create an identifier member.
2.4.5.4. Primary Geometry

If a type with identity has multiple geometry properties, one of them must be designated as primary geometry in order for ldproxy to a) use this geometry for bbox-queries, and to b) encode this property within the GeoJSON geometry or the JSON-FG where member.

Note
Relevant geometry properties must directly be defined by the type with identity (or one of its supertypes). In other words, the target does not look at geometry properties in inlined (data) types when searching for the primary geometry.
Note
If the type only has a single geometry property, ldproxy automatically deduces that it is the primary geometry.

The property that contains the primary geometry is identified by setting tagged value defaultGeometry on the property to the value true. If multiple such properties exist, none of them is selected as primary geometry (because no informed choice can be made) and an error will be logged.

The primary geometry property is encoded with role: PRIMARY_GEOMETRY.

Note
If the primary geometry property has a maximum multiplicity greater than 1, then ShapeChange will log a warning and assume a maximum multiplicity of exactly 1.
Note
Additional geometry properties are encoded like all other UML properties.
Note
The ldproxy target expects all geometry properties to have a maximum multiplicity of exactly 1. That is because ldproxy supports multi-geometry types (e.g. MULTI_POINT and GEOMETRY_COLLECTION), which are typically used in implementations that rely upon the Simple Feature Access standard (such as spatial databases which typically implement the Simple Feature Access - Part 2: SQL Option), but does not define a transformation of a geometry property with max multiplicity greater than 1 to such a multi-geometry type. An according model transformation could be defined and implemented in ShapeChange as a future enhancement. In any case: If the ldproxy target encounters a geometry property with maximum multiplicity greater than 1, it logs an error and continues processing, assuming a maximum multiplicity of exactly 1.
2.4.5.5. Primary Temporal Properties

If a type with identity has multiple temporal properties, i.e. properties whose type is mapped to DATE or DATETIME, then the ldproxy target looks for tagged values defaultInstant, defaultIntervalStart, and defaultIntervalEnd with value true on these properties, in order to determine whether one of them defines the temporal extent of the type.

  • Use of defaultInstant and defaultIntervalStart / defaultIntervalEnd are mutually exclusive. If defaultInstant is true on one of these properties, then the other tags must not be true, and vice-versa. An error will be logged if that is not the case.

  • If defaultInstant is true on one property, then the according property will be encoded with role: PRIMARY_INSTANT. If more than one such property was found, an error will be logged.

  • If defaultIntervalStart is true on one property, then the according property will be encoded with role: PRIMARY_INTERVAL_START. If more than one such property was found, an error will be logged.

  • If defaultIntervalEnd is true on one property, then the according property will be encoded with role: PRIMARY_INTERVAL_END. If more than one such property was found, an error will be logged.

Warning
If none of the temporal properties of the type with identity is marked as PRIMARY_INSTANT, PRIMARY_INTERVAL_START, or PRIMARY_INTERVAL_END, then the first temporal property (following the order in which the properties are encoded in the provider type definition) will automatically be marked as PRIMARY_INSTANT. This reflects the behavior of ldproxy. If this is not desirable for a given type, then define which of the temporal properties should be used as primary instant or interval start / end.
Note
The search for temporal properties that define primary instant / interval is performed on top-level properties only. I.e., properties of inlined (data) types are not considered by this search.
Note
The ldproxy target expects all default temporal properties to have a maximum multiplicity of exactly 1. If a default temporal property with maximum multiplicity greater than 1 is encountered, the target logs an error and continues processing, assuming a maximum multiplicity of exactly 1.
Note
A property with value type TM_Period cannot directly be used for the definition of the temporal extent of a feature, at least not with this ShapeChange target, since ldproxy expects the information of a temporal interval to be given via two separate time instants (the interval start and end). In the future, a ShapeChange transformation could be added, to convert a property with value type TM_Period (and some indicator that the property defines the temporal extent of a type with identity) to two properties, with value type TM_Instant, and with the tags defaultIntervalStart / defaultIntervalEnd.
Note
Additional temporal properties are encoded like all other UML properties.

2.4.6. Data Type

By default, a <<dataType>> is not converted to a top-level provider type definition. Instead, the data type will be encoded as a fragment definition (if fragments are enabled, i.e. target parameter enableFragments = true), and the type definition for the data type is encoded whenever a property, whose value type is the data type, is encoded.

The following information items are encoded for the type definition of the <<dataType>>:

  • type: OBJECT or OBJECT_ARRAY (depending on the multiplicity; for further details, see Property Type)

  • objectType: original name of the data type (taken from tagged value originalClassName, if present, otherwise it is the class name as found in the - potentially transformed and thus altered - model)

  • sourcePath: as determined from configured SQL encoding infos, or as defined for data type valued properties in section Source Paths

  • In fragment definitions:

    • label: value as derived using the labelTemplate (see the documentation section for further details)

    • description: value as derived using the descriptionTemplate (see the documentation section for further details)

  • properties: as documented in section Properties

Note
Although not recommended, data types can have circular dependencies on each other. The ldproxy target does not support such dependencies (because it can lead to an infinite loop of inlined data type definitions). If a circular dependency is detected by the target, it will report an error - and not encode the property that would cause this circular dependency.

2.4.7. Mixin Type

Since v2.14.0, mixins are supported, if target parameter enableFragments is set to true. For further details, see section Inheritance and Specialization.

Note
ShapeChange supports the notion of mixin type (for further details, see Support for Mixin Classes). They are primarily used by the XML Schema target and were meant to support multiple inheritance in an encoding for an implementation technology that does not support multiple inheritance - such as XML Schema.

2.4.8. Union

Conversion of unions is not supported by the ldproxy target.

Note
You can transform unions, either flattening them (using the Flattener rule-trf-prop-flatten-types), or by mapping them (using the Type Converter rule-trf-switchValueTypes, or a map entry defined in the ldproxy target).

2.4.9. Enumeration and Code List

Enumerations and code lists are not converted to top-level provider type definitions. Each <<enumeration>> / <<codelist>> that a) is not mapped, b) is not marked to not be encoded, and c) belongs to the schemas selected for processing, is converted to a {id}.yml file in the data/store/entities/codelists folder. The ldproxy target thus also converts enumerations to ldproxy code lists. The ID thereby is the enumeration / code list name, with all non-word characters replaced by '_'.

The following information items are encoded within the YAML file:

  • id: the enumeration / code list ID

  • label: value as derived using the labelTemplate (see the documentation section for further details)

  • sourceType: TEMPLATES

  • entries: One entry {code}: {target_value} per enum / code defined by the enumeration / code list

    • An enum / code is represented by an attribute in the UML model.

    • If rule-ldp2-cls-codelist-direct applies, then the {code} value is the initial value, and the {target_value} is the enum / code name.

      • NOTE: The ldproxy target will log a warning if a code/enum has no initial value, and proceed by using the enum / code name as {code} value.

    • If rule-ldp2-cls-codelist-targetbytaggedvalue applies, then the {code} value is the initial value, if defined, otherwise it is the enum / code name, and the {target_value} is given by tagged value ldpCodeTargetValue on the enum / code attribute.

      • NOTE: The name of the tag can be configured using target parameter codeTargetTagName (having default value ldpCodeTargetValue). If you choose a different tag name, and that name is not one of the well-known tag names (as listed here), make sure that you set input parameter addTaggedValues with either the tag name or value *. If the tag is used as alias in a tag mapping, and thus mapped to a different tag name, either remove that mapping or choose a different tag.

      • NOTE: The ldproxy target will log a warning if a code/enum has a blank value for the tag, and proceed by using the enum / code name as {target_value}.

    • Otherwise, i.e. neither of the two conversion rules applies, the ldproxy target will encode both {code} and {target_value} with the name of the enum / code. So this will result in a one to one mapping of the enum / code.

    • The resulting {target_value} can be modified:

      • If rule-ldp2-cls-codelist-append-code applies to the enumeration or code list, then the following suffix is appended to the {target_value}: ´' (' + {code} + ')'´. For example, if {code} = ´1000´ and {target_value} = ´ABC´, then the new {target_value} will be ´ABC (1000)´. This addition can be useful for constructing queries, since a query for code value ´ABC´ would in fact have to be written as a query with value ´1000´. The suffix of the {target_value} then shows which value needs to be used in a query.

  • fallback: The value is given by tagged value ldpFallbackValue on the enumeration / code list. If the tagged value is blank (missing or empty), then the fallback is omitted. NOTE: The fallback value will be used (as-is) by ldproxy if a value stored in the database does not match any of the entries defined in the ldproxy code list (which can happen if a code list has evolved since the ldproxy code list has been created). An example for a fallback value would be 'unknown'.

Note
If both rule-ldp2-cls-codelist-direct and rule-ldp2-cls-codelist-targetbytaggedvalue apply to a code list / enumeration, then rule-ldp2-cls-codelist-direct is chosen.
Note

rule-ldp2-cls-codelist-targetbytaggedvalue is useful in combination with model transformations that populate a code list, e.g. by retrieving the code list definition from some registry. Since the target value of an entity within an ldproxy hosted code list can be all sorts of things - from human readable text, over URL, to some Markdown expression - it is better to rely on model transformations to create the ldpCodeTargetValue tagged value as required for a given API deployment. Such model transformations are future work.

In addition, whenever a property, whose value type is the enumeration / code list, information is added both to the provider and the service configurations.

The following information items are added to the property encoding in the provider configuration:

  • type: default is STRING; if tagged value numericType on the enumeration / code list is not blank, then the type results by mapping the type name given by the tagged value.

  • codelist constraint: the codelist ID

  • If rule-ldp2-cls-enumeration-enum-constraint applies to an enumeration, an enum constraint is added. If the enums have initial values, these are used within the constraint - otherwise, the enum names are used.

Note
If the enumeration / code list itself is not encoded, is mapped, or does not belong to the schemas selected for processing, ShapeChange will log a warning, informing the user that this situation is an issue unless an ldproxy codelist with corresponding ID has already been or will be established for the desired deployment by other means (e.g. by manually creating it).
Note
Depending upon the use case, it may or may not be useful to convert enumerations to code lists before executing the ldproxy target, using the Type Converter rule-trf-enumeration-to-codelist. An advantage would be that transformations that apply to code lists could then also be applied to enumerations. A disadvantage would be that rule-ldp2-cls-enumeration-enum-constraint would then no longer be applied, since the types that have originally been enumerations would then be code lists.

The following information is added to the collection definition (within the service configuration) of the global type in which the UML property is encoded, API building block FEATURES_HTML, member transformations: a member whose name is the '.'-concatenated path to the property within the type definition. The value of the new member is an object, to which a codelist member is added, with value being the ID of the enumeration / code list.

Listing 1. Addition of codelist transformations for properties in the service configuration
1
2
3
4
5
6
7
8
9
collections:
  classxyz:
    api:
    - buildingBlock: FEATURES_HTML
      transformations:
        propertya.propertyb.propertyc:
          codelist: MyEnumeration
        propertyd:
          codelist: MyCodelist

2.4.10. Basic Type

Note
The ldproxy target does not support the conversion of basic types yet. This section describes how a conversion could look like.

If a direct or indirect supertype of an application schema class is mapped to one of the simple types FLOAT, INTEGER, STRING, BOOLEAN, DATETIME, or DATE, then the class would represent a so called basic type.

A basic type does not define an object. It represents a simple data value, e.g. a string. The ldproxy encoding of a basic type would just use the simple type to which the direct or indirect supertype is mapped.

Note
In the future, ways to convert restrictions defined by basic types could be defined, using the constraints member (with enum, min, max, or regex). Constraints supported by ldproxy are documented here.

2.5. Properties

The following sections describe how a property from a type with identity, mixin, or data type is converted by the ldproxy target.

Note
The order in which the properties are encoded in the provider definition(s) is defined by the sequenceNumber tagged values of these properties.
Note
The conversion of properties from other kinds of classifiers, especially enumerations and code lists, is described in the according subsections of the Types section.

2.5.1. Source Paths

The type definition within an ldproxy feature provider configuration (including any fragment definitions) describes the full encoding of a particular object type. Inlined property values can lead to a complex structure, especially when the type of a property is a complex <<dataType>>. In order to extract the values for populating the information items of an actual object, ldproxy needs to know the so called source paths. Such a path starts with the name of a database table at the top-level provider type definition. For the properties within a given type definition, the source path construction then depends on the actual representation of the property and its value type within the database.

The target first tries to look up the source path for a given property in configured SQL encoding infos. If no encoding infos are available, the target constructs the path itself. A crucial aspect thereby is the name of the table column that represents the property in the database. Section Database Column Name defines how that name is constructed by the target. With the column name, a statement can be created to access the value(s) of the property. That statement may include table joins. The necessary conversion behavior is defined in section Accessing Property Values.

2.5.1.1. Database Column Name

Whenever a property from the application schema is encoded within an ldproxy provider configuration, the name of the database column that represents that property is required for constructing source paths.

Note
The target will first attempt to identify the source path from SQL encoding infos.

The name is determined as follows:

  • Basically, the property name is used as column name.

  • A suffix can be added to the column name, depending upon the property value type:

    • If the value type is not mapped to or implemented as an ldproxy simple or geometry type, and is a:

      • type with identity (i.e. feature or object type), and:

        • the property belongs to a reflexive association, and the column belongs to an associative table, then the value of target parameter associativeTableColumnSuffix (with default value being the value of target parameter primaryKeyColumn) is used as suffix;

        • otherwise, if the property belongs to a reflexive association, and target parameter reflexiveRelationshipFieldSuffix has a non-blank value (with default being the empty string), then that value is used as suffix;

        • otherwise, the value of target parameter foreignKeyColumnSuffix (with default value being the empty string) is used as suffix

      • data type, then the value of target parameter foreignKeyColumnSuffixDatatype (with default value being the empty string) is used as suffix

    • Otherwise, if the value type is a code list (which is typically mapped to or implemented as an ldproxy simple type), and the code list matches rule-ldp2-cls-codelist-byTable (indicating that the code list is represented in the SQL database by a table), then the value of target parameter foreignKeyColumnSuffixCodelist (with default value being the empty string) is used as suffix.

  • In addition, the column name established so far is converted to lower case (using the english locale).

  • Finally, the column name is restricted to a substring (starting at the beginning of the name) whose length does not exceed the value of target parameter maxNameLength (whose default value is 63 [characters]).

Note

In the future, conversion rules can be defined to modify the default naming behavior.

2.5.1.2. Accessing Property Values

Constructing the source path within a property definition for accessing the property value(s) must consider the type of relationship between the property and its value type, the category of the property value type, the representation of the property value(s) in the database, and type mappings defined in the configuration.

Note
Since v2.14.0, the target first attempts to look up the source path for a property in the SQL encoding infos, taking into account the current encoding context (especially the table that represents the type for which the property is encoded). If no source path was found that way, the target constructs a source path itself, as described in this section.

If the property value type is mapped to a simple type or a geometry type, or if the value type is an enumeration or code list (that does NOT match rule-ldp2-cls-codelist-byTable), source paths are constructed as shown in Figure 2.

ldp2 simple types default source path encoding
Figure 2. Default source path construction for value types that are mapped to simple and geometry types

The abbreviations used in Figure 2 (as well as in the following figures) thereby mean the following:

  • {pk_col_A} - Primary key column in the table that represents type A. The primary key column is defined (in descending order of priority):

    • via the <<identifier>> property of type A (as described here), or

    • as the value of target parameter primaryKeyColumn

  • {A_table_name} - Table name for type A, as defined in section Database Table Name.

  • {pX_col} - The name of the column that represents the property pX, as defined in section Database Column Name.

Note
If defined at all, tag associativeTable is typically found on an attribute or an association.
Note
By default, the SqlDdl target encodes associative tables without a separate primary key column. Instead, the primary key is a combination of multiple columns (e.g. the two columns in a table which represents a 1:n relationship for a property with a value type that is mapped to a simple type). When addressing such tables with a source path, a sort key must explicitly be stated, since the default sort key (stated in the sourcePathDefaults of the provider configuration) does not apply there. However, if these tables are encoded by the SqlDdl target with rule-sql-all-associativeTablesWithSeparatePkField, then the combined primary key in these associative tables is replaced by a separate primary key field, whose name is the value of SqlDdl target parameter idColumnName. As stated in section Provider Configuration, that parameter value corresponds to the ldproxy target parameter primaryKeyColumn, which is also the default sort key (in sourcePathDefaults). Thus, with such a structure for associative tables, there is no need to explicitly define the sort key within the source path. To inform the ldproxy target that associative tables always have a separate primary key column, add rule-ldp2-all-associativeTablesWithSeparatePkField to the encoding rule.

Otherwise, if the property value type is a code list that does match rule-ldp2-cls-codelist-byTable, the target assumes that the code list is represented in the SQL database by a table. In that case, source paths are constructed as shown in Figure 3.

ldp2 codelist bytable source path encoding
Figure 3. Source path construction for code list value types that match rule-ldp2-cls-codelist-byTable

Otherwise, if the property value type is mapped to LINK, the target assumes that the property representation in the database is an identifier, with which a reference to the actual object can be constructed. That reference will be encoded as a link-object (for further details, see section Property Type). If the maximum multiplicity is greater than 1, the target assumes that an associative table exists in the database. Source paths are then constructed as shown in Figure 4.

ldp2 mapped types default source path encoding
Figure 4. Default source path construction for value types that are mapped to LINK

Otherwise, if the property value type is a data type, and:

  • the data type matches rule-ldp2-cls-data-types-oneToMany-severalTables, then source paths are constructed as shown in Figure 5;

  • otherwise, source paths are constructed as shown in Figure 6

ldp2 data types source path encoding onetomany severaltables
Figure 5. Source path construction for value types that are data types and match rule-ldp2-cls-data-types-oneToMany-severalTables
ldp2 data types default source path encoding
Figure 6. Default source path construction for value types that are data types

Otherwise, if the property value type is a type with identity, which are implemented as link objects, and the property does NOT match rule-ldp2-all-linkObjectAsFeatureRef, source paths are constructed as shown in Figure 7 and Figure 8.

ldp2 types with identity default source path encoding
Figure 7. Default source path construction for value types that are types with identity
ldp2 reflexive association source path encoding
Figure 8. Default source path construction for reflexive associations for a type with identity
Note
The default source path construction behavior makes assumptions about the naming and structure (e.g. the columns) of associative tables in the database. If different naming or structure applies for associative tables, additional configuration (via tagged values in the model and/or configuration items [target parameters, conversion rules, map entry parameters and characteristics]) would be needed. The ldproxy target can be enhanced accordingly, if necessary.

Otherwise, if the property value type is a type with identity, which are implemented as feature references, i.e., the property DOES match rule-ldp2-all-linkObjectAsFeatureRef, source paths are constructed as shown in Figure 9 and Figure 10.

ldp2 types with identity feature ref source path encoding
Figure 9. Feature reference source path construction for value types that are types with identity
ldp2 reflexive association feature ref source path encoding
Figure 10. Feature reference source path construction for reflexive associations for a type with identity

2.5.2. Property Type

The type member of a property definition depends upon the value type of the property, as well as its multiplicity.

  • If the maximum multiplicity of the property is greater than 1, and:

    • the value type is mapped to or implemented by a simple type, then the type is VALUE_ARRAY, and an additional valueType member is added, with the name of the simple type as value.

      • NOTE: The ldproxy target does not support geometry properties with multiplicity greater than 1. Such cases should be modeled as property with max multiplicity 1 and a multi-geometry (e.g. GM_MultiPoint) or geometry collection (GM_Aggregate) as value type. If the ldproxy target encounters a geometry property with max multiplicity greater than 1, it will log an error and continue processing, assuming max multiplicity equal to 1 for the property.

    • the value type is mapped to LINK or a type with identity, and:

      • the property matches rule-ldp2-all-linkObjectAsFeatureRef, the value type is encoded as a feature reference, the type is FEATURE_REF_ARRAY, and either refUriTemplate is added, or a refType with the identifier of the value type. Further details on the encoding of a FEATURE_REF are given here.

      • otherwise, the value type is implemented as a link object, the type is OBJECT_ARRAY, and a link object is created in the property definition as defined below.

  • Otherwise, i.e. the maximum multiplicity of the property is equal to 1:

    • If the value type is mapped to a simple ldproxy type, then type is the target type defined by the map entry.

    • Otherwise, if the value type is mapped to a geometry type, then type is GEOMETRY and an additional geometryType member is added, with value as defined by the map entry (via the according characteristic of map entry parameter geometryInfos).

    • Otherwise, if the value type is an enumeration or code list, then type is STRING or a numeric type, as explained in the Enumeration and Code List section.

    • Otherwise, if the value type is implemented as OBJECT but is not a type with identity (so most likely it is a data type), type simply is OBJECT.

    • Otherwise, if the value type is mapped to LINK, or a type with identity, and:

      • the property matches rule-ldp2-all-linkObjectAsFeatureRef, the value type is encoded as a feature reference, the type is FEATURE_REF, and either refUriTemplate is added, or a refType with the identifier of the value type. Further details on the encoding of a FEATURE_REF are given here.

      • otherwise, the value type is implemented as a link object, the type is OBJECT, and a link object is created in the property definition as defined below.

  • objectType: Link

  • sourcePath: As defined for the property (for details, see section Source Paths)

  • properties:

    • title:

      • label: {value_type_name}-title

      • sourcePath: as defined for the property (for details, see section Source Paths)

        • NOTE: If tag ldpTitleAttribute on the value type has a valid value (i.e., it contains the name of an attribute of the value type), and that attribute of the value type is optional (i.e., it has a minimum multiplicity of 0), then: a) sourcePaths is used instead of sourcePath, and b) the name of the primary key column for (the table representing the) value type is added as another source path value - to be used as fallback in case that the title attribute on the value type has no value.

        • NOTE: If tag ldpTitleAttribute is defined on a supertype, and the ShapeChange workflow includes the Flattener for transforming inheritance, then the workflow should also include the tagged value transformer, with rule-trf-taggedValue-inheritance to ensure that tag ldpTitleAttribute is copied to all subtypes - before inheritance hierarchies are flattened. That will ensure that the ldproxy target can find the tag on all subtypes, even though inheritance hierarchies have been flattened.

      • type: STRING

    • href:

      • label: {value_type_name}-ID

      • sourcePath: as defined for the property (for details, see section Source Paths)

      • type: STRING

      • transformations:

        • stringFormat: Either the URL template from the map entry, if one is defined for the property value type, or '{{serviceUrl}}/collections/{value_type_name}/items/{{value}}', where value_type_name is the name of the value type (formatted according to target parameter [collectionIdFormat]) (and {{serviceUrl}} as well as {{value}} will automatically be replaced by ldproxy).

The definition of a FEATURE_REF within a property definition is as follows:

  • If only a single source path was determined: sourcePath, as defined for the property (for details, see section Source Paths)

    • NOTE: If a specific title is defined for the value type, then the source path is for the actual value of the FEATURE_REF. Otherwise, it is the identifier of the referenced feature (which can be a foreign key column).

  • type: FEATURE_REF, if the maximum multiplicity of the property is 1, otherwise type: FEATURE_REF_ARRAY

  • If the value type is mapped to LINK: refUriTemplate is added, with the template value being determined like the stringFormat-transformation of a link object href-member.

  • Otherwise, i.e., the value type is NOT mapped to LINK, it depends:

    • If a single source path was determined for the FEATURE_REF:

      • refType is added, with the identifier of the value type as value.

      • If tag ldpTitleAttribute on the value type has a valid value (i.e., it contains the name of an attribute of the value type), then properties with two members is added:

        • Member id, with:

          • sourcePath: path for the ID member of the value type

          • type: ldproxy type which corresponds to the type of the identifier

        • Member title:

          • sourcePath: path for the title attribute of the value type

            • NOTE: If tag ldpTitleAttribute on the value type has a valid value (i.e., it contains the name of an attribute of the value type), and that attribute of the value type is optional (i.e., it has a minimum multiplicity of 0), then: a) sourcePaths is used instead of sourcePath, and b) the name of the primary key column for (the table representing the) value type is added as another source path value - to be used as fallback in case that the title attribute on the value type has no value.

          • type: ldproxy type which corresponds to the type of the title attribute.

          • label: {value type name} + "-title"

      • Otherwise, i.e., we have a single source path and tag ldpTitleAttribute on the value type does NOT have a valid value:

        • valueType is added, with the ldproxy type of the ID member in the value type definition.

    • Otherwise, i.e., multiple source paths were determined for the FEATURE_REF:

      • If the source paths all have the same value - which can happen in cases where features are stored in the same place, and an additional type discriminator field exists in the data store - like in the Coretable Approach, or if tag ldpTypeAttribute on the the value type has a valid value:

        • properties with a type member is added:

          • The sourcePath of that type member is the path to the type discriminator field.

          • Another type member defines the type of the discriminator value (typically STRING).

          • An enum constraint is added, with one value per relevant type identifier.

        • If tag ldpTitleAttribute on the value type has a valid value, id and title members are also encoded within the properties member, as described before.

      • Otherwise, i.e. multiple source paths with different value were determined:

        • concat or coalesce is used to encode the individual source path options. The former is used if the maximum multiplicity of the property is greater than one, the latter if it is equal to one. An example is shown in section Inheritance and Specialization.

        • Per case within concat or coalesce:

          • sourcePath: One of the source path values.

          • refType is added, with value being the identifier of the actual (value) type that is targeted by the source path.

          • If tag ldpTitleAttribute on the value type has a valid value, id and title members are encoded within a properties member, as described before.

Note
The inlineOrByReference tagged value of the property is ignored by the ldproxy target.

2.5.3. Multiplicity and Voidable

The behavior for encoding the type member of a property definition in a provider type configuration, depending on the maximum multiplicity of the property, is already defined in the Property Type section.

Additional constraints may be added to the provider configuration, based upon the multiplicity and voidability of the property:

  • Constraint required is added, with value true, unless the minimum multiplicity of the property is 0 or the property is voidable.

    • NOTE: A voidable property is a UML property with stereotype <<voidable>>, or with tagged value nillable = true.

  • If the maximum multiplicity of the property is greater than 1:

    • Constraint minOccurrence is added, with value being the minimum multiplicity defined for the property. However, if the property is voidable, then the value is set to 0.

    • Constraint maxOccurrence is added, with value being the maximum multiplicity defined for the property. However, the constraint will not be added if the maximum multiplicity is '*'.

2.5.4. readOnly

With rule-ldp2-prop-readOnly, the ldproxy representation of a UML property that is read-only will include the initial value (if set) within the constantValue member. The constantValue member then replaces the sourcePath in the property definition.

2.5.5. Initial Value

Initial values are only relevant for 'normal' attributes (i.e. attributes that do not represent enums or codes), in combination with readOnly (for further details, see the readOnly section). ldproxy does not (yet) have any specific configuration item to represent initial values of 'normal' attributes that are not readOnly.

2.5.6. Unit of Measure

If target parameter uomTaggedValueName (without default value) is set, the target looks for a tagged value with that name on each property whose value type maps to the ldproxy FLOAT or INTEGER type. If the tag exists and has a non-blank value, the member unit is added to the property definition in the provider configuration, with the tag value as value.

2.5.7. Additional Service Configuration Items

This section documents how additional items may be defined in the service configuration, based upon conversion of a UML property.

Note
Currently, the only items covered are transformations within the Features HTML API-Module. In the future, additional API-Modules can be covered as well.
2.5.7.1. Features HTML API-Module, Property Transformations

The service configuration contains a collection definition of the global type in which a UML property is encoded. Within the API building block FEATURES_HTML, member transformations exists. If one or more of the following conditions are met by the UML property, an additional member is created in the transformations object value. The name of the new member is the '.'-concatenated path to the property within the type definition. The value of the new member is an object, which will contain one or more members that define the transformations to execute for this property.

  • If the property has tag ldpRemove with value IN_COLLECTION, ALWAYS or NEVER, then a remove member is added, with the tagged value as value.

  • If the property value type is mapped to DATE, and the dateFormat target parameter (without default value) has a non-blank value, then a dateFormat member is added, with the parameter value as value.

  • If the property value type is mapped to DATETIME, and the dateTimeFormat target parameter (without default value) has a non-blank value, then a dateFormat member is added, with the parameter value as value.

Listing 2. Addition of transformations for a property in the service configuration
1
2
3
4
5
6
7
8
9
collections:
  classxyz:
    api:
    - buildingBlock: FEATURES_HTML
      transformations:
        propertya.propertyb.propertyc:
          remove: IN_COLLECTION
        propertyd:
          dateFormat: dd.MM.yyyy

2.6. Association Class

There is no native representation for association classes in ldproxy. For schemas that include association classes, a transformation of association classes as defined by GML 3.3 and implemented by the ShapeChange Association Class Mapper should be used.

2.7. Constraints

OCL constraints can be used to enrich a conceptual model with requirements that cannot be expressed in UML alone. The ldproxy target does not support conversion of these constraints.

2.8. Additional rules

If rule-ldp2-all-notEncoded applies to an element of the application schema, then that element and all its components are not encoded.

Note
How to define the encoding rule that applies to an application schema element is documented in more detail here. The ShapeChange configuration file StandardRules.xml defines an encoding rule named "notEncoded", which includes rule-ldp2-all-notEncoded. When StandardRules.xml is included in the configuration of the ldproxy target (typically using an xinclude XML element), then by setting tagged value ldp2EncodingRule to "notEncoded", one would achieve that that model element is not encoded in the ldproxy configuration files.
Note
If a property is encountered whose value type is not encoded (rule-ldp2-all-notEncoded applies to the value type), the ldproxy target will log an error and ignore the property.

2.9. Specific rules

2.9.1. Conversion of generic value types

(since v2.14.0)

Some domains use constructs like the one shown in Figure 11 to add extension points to their feature types. The generic attributes shown in this example contain a name and a (simple) value. They provide a specific place for adding further information in a key-value-pair based fashion.

ldp2 specificrules genericvaluetypes
Figure 11. Example schema with generic value types

There is a specific solution for supporting such structures with ldproxy.

The according conversion is enabled using rule-ldp2-cls-genericValueType. The conversion rule is applied for a <<dataType>> whose name is contained in the (comma-separated) value of target parameter genericValueTypes. The subtypes will automatically be taken into account (so do not list them in the parameter value). For the example, genericValueTypes=GenerAttribute would thus suffice.

The provider configuration for FT4 would contain the definitions listed in Listing 3.

Listing 3. Generic value type encoding in the provider configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  someGenerAttribute:
    type: OBJECT
    objectType: GenerAttribute
    label: GenerAttribute
    description: The description of type GenerAttribute.
    properties:
      name:
        sourcePath: name
        type: STRING
        label: name
        description: Description of attribute 'name'.
        constraints:
          required: true
      dataType:
        sourcePath: datatype
        type: STRING
        label: data type
        constraints:
          required: true
          enum:
          - IntegerAttribute
          - DoubleAttribute
          - StringAttribute
          - DateAttribute
          - UrlAttribute
      value:
        type: VALUE
        label: value
        coalesce:
        - sourcePath: value_integer
          type: INTEGER
        - sourcePath: value_double
          type: FLOAT
        - sourcePath: value_string
          type: STRING
        - sourcePath: value_date
          type: DATE
        - sourcePath: value_uri
          type: STRING
  otherGenerAttribute:
    type: OBJECT_ARRAY
    objectType: GenerAttribute
    label: GenerAttribute
    description: The description of type GenerAttribute.
    properties:
      name:
        sourcePath: name
        type: STRING
        label: name
        description: Description of attribute 'name'.
        constraints:
          required: true
      dataType:
        sourcePath: datatype
        type: STRING
        label: data type
        constraints:
          required: true
          enum:
          - IntegerAttribute
          - DoubleAttribute
          - StringAttribute
          - DateAttribute
          - UrlAttribute
      value:
        type: VALUE
        label: value
        coalesce:
        - sourcePath: value_IntegerAttribute
          type: INTEGER
        - sourcePath: value_double
          type: FLOAT
        - sourcePath: value_string
          type: STRING
        - sourcePath: value_DateAttribute
          type: DATE
        - sourcePath: value_UrlAttribute
          type: STRING

The sourcePath values within value.coalesce are constructed using the template {attribute name} + "_" + {suffix} - where the suffix default is the name of the attribute value type. That default can be overwritten by setting tagged value ldpGenericValueTypeSuffix on the attribute. In the example, that is the case for the attributes StringAttribute.value as well as DoubleAttribute.value.

Note
If fragments are enabled (target parameter enableFragments = true), a single fragment definition for GenerAttribute would be created, and referenced in the definitions of someGenerAttribute and otherGenerAttribute.

The sourcePath for someGenerAttribute and otherGenerAttribute is not shown in Listing 3. The path would be constructed as usual for any data type valued property. For further details, see Source Paths.

Note
rule-ldp2-cls-genericValueType only looks for a single attribute that is common to all subtypes of the classes identified by target parameter genericValueTypes. Additional properties of these subtypes are ignored! Also, if multiple common properties exist, all will be ignored (and an error logged)!

The primary purpose of the dataType property is to support compliant GML output. The enumeration is constructed with the names of the subtypes of the generic value type. If building block Features - GML is enabled, then the service configuration would declare variableObjectElementNames (one per generic value type) for building block GML, as shown in the following example.

1
2
3
4
5
6
7
8
9
10
11
- buildingBlock: GML
  enabled: true
  variableObjectElementNames:
    GenerAttribute:
      property: dataType
      mapping:
        IntegerAttribute: ns:IntegerAttribute
        DoubleAttribute: ns:DoubleAttribute
        StringAttribute: ns:StringAttribute
        DateAttribute: ns:DateAttribute
        UrlAttribute: ns:UrlAttribute
Note
The namespace prefixes in the mappings are automatically determined by ShapeChange.

Furthermore, in the Features - GeoJSON and Features - JSON-FG building blocks, if enabled, a transformation is added to remove property dataType from the according output. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  ft4:
    id: ft4
    label: ft4
    enabled: true
    api:
    - buildingBlock: GEO_JSON
      transformations:
        otherGenerAttribute.dataType:
        - remove: ALWAYS
        someGenerAttribute.dataType:
        - remove: ALWAYS
    - buildingBlock: JSON_FG
      transformations:
        otherGenerAttribute.dataType:
        - remove: ALWAYS
        someGenerAttribute.dataType:
        - remove: ALWAYS

2.9.2. Coretable Approach

(since v2.14.0)

Application schemas can be quite extensive, and can have classes with quite complex structure. Managing data for that schema in a relational database can be a daunting and demanding task - especially if the database schema is also complex (lots of tables, lots of columns, lots of foreign key and other constraints). Furthermore, changes in the application schema structure, during application schema development, or between application schema versions, require complex database updates. The coretable approach is a way to mitigate the level of complexity. In this approach, the database schema only consists of two tables: a coretable with one entry per object (each object MUST have a globally unique identifier), and a separate references table, where the object references are managed.

To signal that the coretable approach applies, include rule-ldp2-all-coretable in the encoding rule.

The coretable is defined as follows:

  • The table name is given by target parameter coretable (default value is 'features').

  • The table must have a separate primary key column (integer valued). The column name is given by target parameter coretablePkColumn (default value is 'pk').

  • The table has a column with the object identifiers. The identifiers are used in object references, and must be unique (at least within the coretable; UUIDs would be suitable, for example). The column name is given by target parameter coretableIdColumn (default value is the value of target parameter primaryKeyColumn). The ldproxy type of the column is defined via target parameter coretableIdColumnLdproxyType (default is 'INTEGER').

  • The table also has a column in which the name of the feature type of an object is encoded. The name is equal to the ldproxy collection ID for that feature type. The column name is defined via target parameter coretableFeatureTypeColumn (default value is 'featuretype').

  • The table must have a properties column with JSON-encoded value. This column is used to encode all object properties, including object references from data types, but typically not object references from or between types with identity.

    • If a data type is encoded, then any object reference it may have is encoded within the JSON properties as well - NOT in the high priority reference column of the coretable or within the references table. The encoding follows the rules for FEATURE_REFs laid out here. However, the source path is just the name of the property that represents the object reference.

      • NOTE: This encoding does NOT take into account all possibilities of the JSON encoding with rule-json-all-featureRefs, JSON Schema target parameters featureRelProfiles=rel-as-key`, and (potentially also) featureRefWithAnyCollectionId=true. The source path would need to be followed by /featureId if either multiple collections are targeted by the property value type (i.e., the value type is a supertype, with multiple non-abstract types in the subtype hierarchy), or some target parameter that reflected the JSON Schema target parameter featureRefWithAnyCollectionId was set to true. The encoding of /featureId may be added in a future version of the ldproxy target.

    • NOTE: The JSON object does not have an additional level of nesting, like in the case of a GeoJSON-encoded feature. The object properties are directly encoded as members of the JSON object (data type values would of course lead to some level of nesting).

  • The table has a column to store the primary geometry of the object. The column name is given by target parameter coretableGeometryColumn (default value is 'geom').

  • The table may have additional columns (for example, to identify the application schema version), which will be ignored by ldproxy.

The references table is defined as follows:

  • The table name is given by target parameter coretableRelationsTable (default value is 'references').

  • The table must have a separate primary key column, whose name is given by target parameter coretablePkColumn (like in the coretable itself, see above).

  • The table has two columns with the identifiers of the objects that participate in an object-object relationship. The object-object relationship is typically modeled as an association. For a uni-directional association, the direction of the association is unimportant. The owner of the navigable association role automatically is identified as the source of the relationship, and the association role automatically is seen as the target role. However, for a bi-directional association, the direction in which the association was modeled does matter, because source and target must be encoded in separate and distinct columns within the references table. In the bi-directional case, the class that is the source of the association is the source of the relationship, and the other class is the target. The association role that is navigable from the source is the target role, and the other association role is the source role.

    • The column that contains the identifier of the source object is defined by target parameter coretableIdColumn (like in the coretable itself, see above).

    • The column that contains the identifier of the target object is defined by target parameter coretableRefColumn (default value is 'ref').

    • The ldproxy type of both columns is defined by target parameter coretableIdColumnLdproxyType (like in the coretable itself, see above).

  • The references table also has two columns in which the names of the target and the source roles are encoded (for a uni-directional association, only the target role name is provided):

    • The name of the column with the target role is defined by target parameter coretableRelationNameColumn (default value is 'rel').

    • The name of the column with the source role is defined by target parameter coretableInverseRelationNameColumn (default value is 'rel_inv').

    • The ldproxy type of both columns is 'STRING'.

The ldproxy target will create appropriate configurations for this particular database schema.

The coretable approach supports object references whose sources are data types. However, such references MUST be encoded within the JSON-properties. They cannot be represented in the references table.

3. Encoding Rules

For some application schemas, it is useful to know that different encoding rules can be applied to the subpackages, classes, and properties defined by the schema. Typically, a single encoding rule applies to all application schema elements. In ShapeChange, that rule is identified by setting the target parameter defaultEncodingRule, with the unique name defined for the encoding rule in the target configuration. The target configuration, however, can contain multiple encoding rules (with different names). By setting tagged value ldp2EncodingRule on an application schema element, using the name of another encoding rule, the model element will be encoded as defined by that rule.