From 449055fc4a9ed2b6bf22d152461288f0cb1f12d8 Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Wed, 13 Dec 2023 17:56:44 +0100 Subject: [PATCH 01/10] TEDEFO-2944 additions and adaptations for the business entities in fields.json --- modules/fields/pages/business-entities.adoc | 50 +++++++++++++ modules/fields/pages/index.adoc | 80 ++++++++++++--------- modules/fields/pages/xml-structure.adoc | 4 +- modules/fields/partials/nav.adoc | 3 +- modules/notice-viewer/pages/index.adoc | 6 +- 5 files changed, 104 insertions(+), 39 deletions(-) create mode 100644 modules/fields/pages/business-entities.adoc diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc new file mode 100644 index 00000000..748e406f --- /dev/null +++ b/modules/fields/pages/business-entities.adoc @@ -0,0 +1,50 @@ += Business Entities + +== Introduction + +Each field belongs to a business entity, this is independent from the XML representation even if there can be some overlap. +This logical structure is included in the eForms SDK to group information about identifiers and can also be used in a UI to group fields by their business entity. + +== Properties of a business entity + +The following snippet shows the information that can be provided: + +[source,json] +---- + { + "id" : "contract", // <1> + "parentId" : "noticeResult", // <2> + "name" : "Contract", // <3> + "description" : "Information on a contract", // <4> + "repeatable" : true, // <5> + "schemeName" : "contract", // <6> + "instanceIdentifier" : { // <7> + "formatName" : "prefixedNumber", // <8> + "text" : "CON" // <9> + }, + "identifierFieldId" : "OPT-316-Contract", // <10> + "captionFieldId" : "BT-150-Contract" // <11> + }, { + "id" : "contractModification", + "name" : "Contract modification", + "description" : "Information on the modifications", + "repeatable" : true, + "instanceIdentifier" : { + "formatName" : "fixedText", // <8> + "text" : "CONTRACT-MODIFICATION" // <9> + } + } +---- +<1> Identifier of the business entity. +<2> Identifier of the direct parent that contains the business entity (not always present). +<3> A short name. +<4> A descriptive text, it is longer than the "name". +<5> Indicates if the business entity can be repeated inside its parent. +<6> Indicates the schemeName if applicable (we indirectly get the field "schemeName" from there). +<7> An object to document the instance identifier (if applicable). +<8> The format name, for now we have two, the "prefixedNumber" or "fixedText". +<9> The identifier prefix or the fixed text. +<10> Indicates which field id identifies this business entity instance. +<11> Indicates which field id can be used to display this business entity instance to a user. + +NOTE: the fields can have a "businessEntityId" but nodes cannot. diff --git a/modules/fields/pages/index.adoc b/modules/fields/pages/index.adoc index 78543821..0ffbc799 100644 --- a/modules/fields/pages/index.adoc +++ b/modules/fields/pages/index.adoc @@ -65,7 +65,7 @@ We are using this file to provide the definition of all fields to our form-filling application (eNotices2). Each form is then made of a specific subset of those fields. -The field repository is mainly an array of fields, preceded by some version information and the general structure of XML notices: +The field repository is mainly an array of fields, preceded by some version information, the business entities and the general structure of XML notices: [source,json] ---- @@ -76,11 +76,15 @@ The field repository is mainly an array of fields, preceded by some version info "version": "0.2.53", "createdOn": "2021-11-20T16:46:39" }, - "xmlStructure" : [ // <4> + "businessEntities" : [ // <4> + { ... }, + ... + ] + "xmlStructure" : [ // <5> { ... }, ... ], - "fields": [ // <5> + "fields": [ // <6> { ... }, ... ] @@ -89,8 +93,9 @@ The field repository is mainly an array of fields, preceded by some version info <1> Version of the UBL standard used. <2> Version of the eForms SDK the file belongs to. <3> Version number and date of the data used to create this file. -<4> General structure of XML notices. See the xref:xml-structure.adoc[] page. -<5> List of fields. +<4> Logical structure defined by the business entities. See the xref:business-entities.adoc[] page. +<5> General structure of XML notices. See the xref:xml-structure.adoc[] page. +<6> List of fields. == Field properties @@ -108,16 +113,19 @@ The various characteristics of each field are indicated as properties of the JSO "xpathRelative" : "cbc:RegulatoryDomain", // <6> "xsdSequenceOrder" : [ { "cbc:RegulatoryDomain" : 18 } ], // <7> "type" : "code", // <8> - "legalType" : "CODE", // <9> - "maxLength" : 400, // <10> - "repeatable" : { // <11> - "value" : false + "businessEntityId" : "procedure", // <9> + "legalType" : "CODE", // <10> + "maxLength" : 400, // <11> + "repeatable" : { // <12> + "value" : false, + "severity" : "ERROR" }, - "codeList" : { // <12> + "codeList" : { // <13> "value" : { - "id" : "legal-basis", + "id" : "eforms-legal-basis", "type" : "flat" - } + }, + "severity" : "ERROR" } }, { "id" : "BT-137-Lot", @@ -128,13 +136,15 @@ The various characteristics of each field are indicated as properties of the JSO "xpathRelative" : "cbc:ID", "xsdSequenceOrder" : [ { "cbc:ID" : 2 } ], "type" : "id", - "idScheme" : "LOT", // <13> + "attributes" : [ "BT-137-Lot-Scheme" ], + "businessEntityId" : "lot", + "idScheme" : "LOT", // <14> "legalType" : "IDENTIFIER", "repeatable" : { "value" : false, "severity" : "ERROR" }, - "forbidden" : { // <14> + "forbidden" : { // <15> "value" : false, "severity" : "ERROR", "constraints" : [ { @@ -143,7 +153,7 @@ The various characteristics of each field are indicated as properties of the JSO "severity" : "ERROR" } ] }, - "mandatory" : { // <15> + "mandatory" : { // <16> "value" : false, "severity" : "ERROR", "constraints" : [ { @@ -152,7 +162,7 @@ The various characteristics of each field are indicated as properties of the JSO "severity" : "ERROR" } ] }, - "pattern" : { // <16> + "pattern" : { // <17> "value" : "^LOT-\\d{4}$", "severity" : "ERROR" } @@ -165,7 +175,9 @@ The various characteristics of each field are indicated as properties of the JSO "xpathRelative" : "efac:TenderLot/cbc:ID", "xsdSequenceOrder" : [ { "efac:TenderLot" : 14 }, { "cbc:ID" : 1 } ], "type" : "id-ref", - "idSchemes" : [ "LOT", "GLO" ], // <17> + "attributes" : [ "BT-13714-Tender-Scheme" ], + "businessEntityId" : "tender", + "idSchemes" : [ "LOT", "GLO" ], // <18> "legalType" : "IDENTIFIER", "repeatable" : { "value" : false, @@ -192,16 +204,17 @@ The various characteristics of each field are indicated as properties of the JSO <6> Location of the field in an XML notice, relative to its parent node. <7> Position of each XML element relative to its siblings. <>. <8> Technical data type of the field. -<9> Data type of the business term, as indicated in the eForms Regulation. -<10> Maximum number of characters allowed in the value of the field, optional. -<11> Indicates if the field can appear more than once inside its container -<12> Identifier of the code list from which the field value must belong. -Applicable only for fields of type "code" or "internal-code" -<13> Identifier scheme used by a field with `"type" : "id"`. -<14> This property provides information on when a field's presence is forbidden. -<15> This property provides information on when a field's value is mandatory. -<16> A RegEx pattern the field's value must match. -<17> Array indicating the valid `idScheme` values which this identifier reference field (`"type" : "id-ref"`) can reference. +<9> The id of the business entity the field belongs to. +<10> Data type of the business term, as indicated in the eForms Regulation. +<11> Maximum number of characters allowed in the value of the field, optional. +<12> Indicates if the field can appear more than once inside its container +<13> Identifier of the code list from which the field value must belong. +Applicable only for fields of type "code". +<14> Identifier scheme used by a field with `"type" : "id"`. +<15> This property provides information on when a field's presence is forbidden. +<16> This property provides information on when a field's value is mandatory. +<17> A RegEx pattern the field's value must match. +<18> Array indicating the valid `idScheme` values which this identifier reference field (`"type" : "id-ref"`) can reference. === Property Values @@ -221,15 +234,16 @@ The properties that are assigned with static values are listed below: `xpathRelative`:: The XPath of the field relative to its parent `node`. See `parentNodeId`. [#xsdSequenceOrder]`xsdSequenceOrder`:: This indicates, for each XML element that is part of `xpathRelative`, the position that this element should have relative to its siblings in order to have an XML instance valid against the XML Schema. This information is extracted from the definition of the corresponding complex type in the XSD files. `type`:: The data type of the field. xref:#data-types[See Field data types]. -`attributeOf`:: If the field represents an XML attribute this indicates the identifier of the field representing the XML element which has the attribute. `attributeName`:: The name of the XML attribute represented by the field. +`attributeOf`:: If the field represents an XML attribute this indicates the identifier of the field representing the XML element which has the attribute. `attributes`:: An array of one or more identifiers of the fields representing the XML attributes the XML element represented by the field can have. `presetValue`:: The value used to pre-fill a field. This property is always a string, but the value should be converted to the same type as the field. The value "\{NOW\}" corresponds to the current date or time. -`legalType`:: The data type of the Business Term associated with the field as defined by the eForms Regulation. -`maxLength`:: The maximum number of characters that the field can hold. +`businessEntityId`:: The id of the business entity the field belongs to. See xref:fields:business-entities.adoc[Business Entities]. +`idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of valid identifier schemes that this `id-ref` field can reference. `idScheme`:: Applicable only to fields of type `id`. Indicates the identifier scheme for this `id` field (e.g. "TPO" for Touch Point). `schemeName`:: Applicable only to fields of type `id`. Indicates the value that should be indicated for this field in the `schemeName` attribute in the XML. -`idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of valid identifier schemes that this `id-ref` field can reference. +`legalType`:: The data type of the Business Term associated with the field as defined by the eForms Regulation. +`maxLength`:: The maximum number of characters that the field can hold. Static properties are always assigned with a scalar value (a string, a boolean, a number, array of strings, etc.). If there is no value defined, the property is omitted. @@ -417,7 +431,7 @@ In the following snippet, a dynamic value is assigned to the `forbidden` dynamic } ] }, ---- -<1> The default value of the property will be false in this example +<1> The default value of the property will be false in this example. <2> List of constraints for this property. <3> The first constraint in this example specifies a different value than the default one in the case that the field is used in one of the notice types indicated. <4> The value of this dynamic property in the case that the constraint applies is indicated here. @@ -458,7 +472,7 @@ The value of the `condition` property of a constraint is a string representing a This expression is made of two parts: -* The context under which the expression is evaluated. It's often the parent node of the field. +* The context under which the expression is evaluated. It is often the parent node of the field. * The boolean expression itself. diff --git a/modules/fields/pages/xml-structure.adoc b/modules/fields/pages/xml-structure.adoc index 83f11841..404cb7b6 100644 --- a/modules/fields/pages/xml-structure.adoc +++ b/modules/fields/pages/xml-structure.adoc @@ -2,7 +2,7 @@ == Introduction -The field metadata in the fields repository file (fields.json) describe the properties and behaviour of each field. Each field, representing an element in an XML document, is ultimately part of a greater tree-like structure. Actually, there is more than one such structure that each field is a part of: +The field metadata in the fields repository file (fields.json) describes the properties and behaviour of each field. Each field, representing an element in an XML document, is ultimately part of a greater tree-like structure. Actually, there is more than one such structure that each field is a part of: * The physical structure in which each field is stored inside the notice XML file. This page documents how this physical structure is represented in the SDK. @@ -15,7 +15,7 @@ This physical structure (XML structure) is included in the eForms SDK to allow i == XML structure in the field repository -The XML structure is provided as a flat list of "nodes" at the end of the field repository file (fields.json). Every node represents an XML element. Each node can "contain" other nodes and/or fields. Every field provides a `parentNodeId` property which points to its parent node in the XML structure. Every node provides a `parentId` property which points to its parent node. Using this information you can reconstruct the entire XML tree. The absolute XPath of each node is also provided as well as the XPath relative to its parent node. +The XML structure is provided as an array called "xmlStructure" near the top of field repository file (fields.json). Every item represents an XML element. Each item (a node) can "contain" other nodes and/or fields. Every field provides a `parentNodeId` property which points to its parent node in the XML structure. Every node provides a `parentId` property which points to its parent node (except the root). Using this information you can reconstruct the entire XML tree. The absolute XPath of each node is also provided as well as the XPath relative to its parent node. NOTE: The `xmlStructure` list provided in fields.json is a flat list. The logical hierarchy of the nodes is represented using the `parentId` property. diff --git a/modules/fields/partials/nav.adoc b/modules/fields/partials/nav.adoc index 676ed03e..fc15c56b 100644 --- a/modules/fields/partials/nav.adoc +++ b/modules/fields/partials/nav.adoc @@ -1,2 +1,3 @@ * xref:{page-component-version}@eforms:fields:index.adoc[Field metadata] -** xref:{page-component-version}@eforms:fields:xml-structure.adoc[XML Structure] \ No newline at end of file +** xref:{page-component-version}@eforms:fields:xml-structure.adoc[XML Structure] +** xref:{page-component-version}@eforms:fields:business-entities.adoc[Business Entities] \ No newline at end of file diff --git a/modules/notice-viewer/pages/index.adoc b/modules/notice-viewer/pages/index.adoc index f15d08be..bd99eded 100644 --- a/modules/notice-viewer/pages/index.adoc +++ b/modules/notice-viewer/pages/index.adoc @@ -2,7 +2,7 @@ To demonstrate how you can use the eForms SDK in a *metadata driven application* that visualises eForms notices, we have created this sample application. The application is https://github.com/OP-TED/eforms-notice-viewer[available on Github]. You are encouraged to use it for inspiration or as a basis for further development. You are also welcome to contribute with pull requests any improvements that you want to share with us and other eSenders. -CAUTION: The notice viewer is not a production ready application. It is intended to demonstrate the use of concepts and resources available in the eForms SDK. You can use it as an inspiration or a starting point for your own apps. +CAUTION: The notice viewer is not a production ready application. It is intended to demonstrate the use of concepts and resources available in the eForms SDK. You can use it as an inspiration or a starting point for your own applications. == Goal @@ -57,7 +57,7 @@ After the XSL is generated, the Saxon XSLT processor is called to apply the XSL If a label is not found in the available version of the SDK, then the label's identifier is displayed instead. -The CSS stylesheet is very basic and uses several colors to visually identify different types of artefacts in the final output. For example, "static" labels are displayed with a different color than "dynamic" labels. A "dynamic" label in this context is a label who's identifier depends on the value of a field (like the label of a codelist or indicator field). Our goal was not to make the notice visually pleasing, but to make the output more clear to a developer exploring the application. +The CSS stylesheet is very basic and uses several colors to visually identify different types of artifacts in the final output. For example, "static" labels are displayed with a different color than "dynamic" labels. A "dynamic" label in this context is a label who's identifier depends on the value of a field (like the label of a codelist or indicator field). Our goal was not to make the notice visually pleasing, but to make the output more clear to a developer exploring the application. NOTE: The application actually tries to use the correct version of the SDK as specified in the XML notice being visualised. However, as view templates were not available before eForms SDK version 0.6.0, the application is unable to render notices created with versions of the SDK prior to 0.6.0. @@ -65,7 +65,7 @@ The section numbers displayed in the HTML notice are automatically generated (ap NOTE: The application tries to implement a mechanism for using multiple versions of the eForms SDK in parallel. However, this first version of the application can only work with one version of the SDK as currently there is no other version of the eForms SDK that contains any view templates. Therefore, the current implementation of the mechanism that handles multiple versions of the SDK in parallel is incomplete. -WARNING: The view templates currently included in SDK 0.7.0 are a "work in progress". You may find templates that contain mistakes or even "to-do" comments included in this version of the SDK. +WARNING: The view templates included in SDK 0.7.0 are a "work in progress". You may find templates that contain mistakes or even "to-do" comments included in this version of the SDK. ''' *See also:* From 2243cef015f490e358dee83a668a5132dcbda7ef Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Mon, 8 Jan 2024 12:48:30 +0100 Subject: [PATCH 02/10] TEDEFO-2944 improving the documentation of the business entities. --- modules/fields/pages/business-entities.adoc | 78 ++++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc index 748e406f..0f4ca458 100644 --- a/modules/fields/pages/business-entities.adoc +++ b/modules/fields/pages/business-entities.adoc @@ -2,12 +2,20 @@ == Introduction -Each field belongs to a business entity, this is independent from the XML representation even if there can be some overlap. -This logical structure is included in the eForms SDK to group information about identifiers and can also be used in a UI to group fields by their business entity. +Some identifiers like for example "PROCEDURE" were not present in the SDK except in the "pattern" of some fields. +This gave us a hint that technical, machine readable information was missing from the SDK. +The information about identifiers was also spread across the fields and patterns with no clear overview. + +To solve this we decided to add business entities to the SDK. +Each field should belong to one and only one business entity. +The business entities are independent from the XML structure even if there can be some overlap. +The business entities describe what we call the logical structure. + +NOTE: the fields can have a "businessEntityId" but we decided that nodes of the `xmlStructure` would have none. == Properties of a business entity -The following snippet shows the information that can be provided: +The following snippet shows cases of information provided about business entities in `fields.json`: [source,json] ---- @@ -36,15 +44,67 @@ The following snippet shows the information that can be provided: } ---- <1> Identifier of the business entity. -<2> Identifier of the direct parent that contains the business entity (not always present). -<3> A short name. +<2> Identifier of the direct parent business entity that contains the business entity (if applicable). +<3> A short name which can be used for display (instead of the id) <4> A descriptive text, it is longer than the "name". <5> Indicates if the business entity can be repeated inside its parent. -<6> Indicates the schemeName if applicable (we indirectly get the field "schemeName" from there). +<6> Indicates the schemeName (if applicable). <7> An object to document the instance identifier (if applicable). <8> The format name, for now we have two, the "prefixedNumber" or "fixedText". <9> The identifier prefix or the fixed text. -<10> Indicates which field id identifies this business entity instance. -<11> Indicates which field id can be used to display this business entity instance to a user. +<10> Indicates which field id identifies this business entity instance (if applicable). +<11> Indicates which field id can be used to display this business entity instance to a user (if applicable). + +== Usage + +=== Interfaces + +==== Grouping fields naturally + +This can be used in a UI to group or filter fields by their business entity. +It can be more natural to group them by business entity than to group them by XML structure node. +In that case the fields can be first sorted by business entity and second by alphabetical order. + +==== Hardcoded identifiers + +Some identifiers like for example "PROCEDURE" were not present in the SDK except in the "pattern" of some fields. +These identifiers are made of fixed text, in the business entities they have `"formatName"` with value `"fixedText"`. +The identifier value is given by the `"text"`, for example `"text" : "PROCEDURE"`. + +==== Detecting changes + +The process of detecting changes could be automated inside of applications. +In order to populate the data of the field `BT-13716-notice` the following logic can be used: + +* If the data of a field was changed +* Read the "businessEntityId" of the field via `fields.json` +* Get the business entity by business entity id via `fields.json` + +After this there are two cases. + +===== Fixed identifiers + +The simplest case is if the business entity has the fixed identifier format `fixedText`. +In that case the `text` gives the identifier that changed. + +===== Prefixed identifiers + +A more complex case is when the identifier has the prefixed number format `prefixedNumber`. +In that case the "instanceIdentifier" field can be found via the business entity. +The field business entity id of a field always points to the most precise business entity. +But if the field is repeatable the application must pick the correct instance, the one to which the changed field belongs. + +=== Usage in XML generation + +In simple cases fields of type `id-ref` can only reference one type of identifier, in that case the scheme name is given. +But in some cases for fields of type `id-ref` the user can select between multiple identifier types. +For example `ORG` or `TPO`, this means the user will decide the `schemeName`, it cannot be determined in advance. +Assuming the user selected `Touch point one (TPO-0001)`: + +* The application puts the correct id `TPO-0001` into the field +* From the value `TPO-0001` the application can extract the `TPO` prefix +* In `fields.json` the application can find the business entity that has the prefix `TPO` +* From the business entity the application can infer the `schemeName` which is `touchpoint` -NOTE: the fields can have a "businessEntityId" but nodes cannot. +The `schemeName` is an XML attribute which must be set on some XML elements and the value must be `touchpoint` in this example. +It is possible to achieve this without the business entities but the business entities make the link more obvious. From 745c6442889e596a1673b65e650fda68f511ead5 Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Mon, 8 Jan 2024 18:15:30 +0100 Subject: [PATCH 03/10] TEDEFO-2944 improvements in the documentation of the business entities, adding a new section about legacy data. --- modules/fields/pages/business-entities.adoc | 123 +++++++++++--------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc index 0f4ca458..663230cf 100644 --- a/modules/fields/pages/business-entities.adoc +++ b/modules/fields/pages/business-entities.adoc @@ -2,103 +2,118 @@ == Introduction -Some identifiers like for example "PROCEDURE" were not present in the SDK except in the "pattern" of some fields. -This gave us a hint that technical, machine readable information was missing from the SDK. -The information about identifiers was also spread across the fields and patterns with no clear overview. +In some fields there are patterns like: + +[source,json] +---- + "pattern" : { + "value" : "^(RESULT|((CON|RES|TEN|TPA|TPO|ORG)-\\d{4}))$", + "severity" : "ERROR" + }, +---- + +Or this pattern: + +[source,json] +---- + "pattern" : { + "value" : "^(PROCEDURE|BUYER|RESULT|((PAR|LOT|GLO|RES|ORG)-\\d{4}))$", + "severity" : "ERROR" + } +---- + +Values like `LOT` are described in various places outside of the pattern. +But some values like `PROCEDURE` only existed in the SDK. +This gave us a hint that machine readable information was missing somewhere in the SDK. +The information about identifiers was spread across the fields, nodes and patterns. + +To solve this we decided to add what we call "business entities" to the SDK. +We also decided that each field should belong to one and only one business entity. +The business entities are independent from the XML structure (nodes). +Thus in `fields.json` the fields have a `businessEntityId` and we decided that nodes of the `xmlStructure` would have none. -To solve this we decided to add business entities to the SDK. -Each field should belong to one and only one business entity. -The business entities are independent from the XML structure even if there can be some overlap. The business entities describe what we call the logical structure. -NOTE: the fields can have a "businessEntityId" but we decided that nodes of the `xmlStructure` would have none. +== Business entities in the SDK + +Business entities are provided as a JSON array called `businessEntities` in the `fields.json` + +[horizontal] +`id`:: Identifier of the business entity. +`parentId`:: Identifier of the direct parent business entity (if applicable). +`name`:: A short name which can be used for display (instead of the id). +`description`:: A descriptive text, it is longer than the `name`. +`repeatable`:: Indicates if the business entity can be repeated inside its parent. +`schemeName`:: Indicates the schemeName (if applicable). +`identifierFieldId`:: Indicates which field id identifies this business entity instance (if applicable). +`captionFieldId`:: Indicates which field id can be used to display this business entity instance to a user (if applicable). +`instanceIdentifier`:: An object to document the instance identifier (if applicable). +`formatName`:: Found in `instanceIdentifier`, the format name, for now we have two, the "prefixedNumber" or "fixedText". +`text`:: Found in `instanceIdentifier`, the identifier prefix or the fixed text. + +== Legacy data -== Properties of a business entity +The business entities make some of the `fields.json` data obsolete. +We will keep this data for backward compatibility reasons, it could be removed in a future SDK. -The following snippet shows cases of information provided about business entities in `fields.json`: +For example: [source,json] ---- - { - "id" : "contract", // <1> - "parentId" : "noticeResult", // <2> - "name" : "Contract", // <3> - "description" : "Information on a contract", // <4> - "repeatable" : true, // <5> - "schemeName" : "contract", // <6> - "instanceIdentifier" : { // <7> - "formatName" : "prefixedNumber", // <8> - "text" : "CON" // <9> - }, - "identifierFieldId" : "OPT-316-Contract", // <10> - "captionFieldId" : "BT-150-Contract" // <11> - }, { - "id" : "contractModification", - "name" : "Contract modification", - "description" : "Information on the modifications", - "repeatable" : true, - "instanceIdentifier" : { - "formatName" : "fixedText", // <8> - "text" : "CONTRACT-MODIFICATION" // <9> - } - } + "businessEntityId" : "groupOfLots", + "idScheme" : "GLO", + "schemeName" : "LotsGroup", ---- -<1> Identifier of the business entity. -<2> Identifier of the direct parent business entity that contains the business entity (if applicable). -<3> A short name which can be used for display (instead of the id) -<4> A descriptive text, it is longer than the "name". -<5> Indicates if the business entity can be repeated inside its parent. -<6> Indicates the schemeName (if applicable). -<7> An object to document the instance identifier (if applicable). -<8> The format name, for now we have two, the "prefixedNumber" or "fixedText". -<9> The identifier prefix or the fixed text. -<10> Indicates which field id identifies this business entity instance (if applicable). -<11> Indicates which field id can be used to display this business entity instance to a user (if applicable). -== Usage +The field `schemeName` is coming from the business entity, it should ideally be retrieved via the business entity of the field. +We will keep this `schemeName` in the `fields.json`. +The same is true for the `idScheme`. -=== Interfaces +There are similar cases for the nodes `identifierFieldId` and `captionFieldId`, both of which are provided by the business entities but the relationship is more indirect. -==== Grouping fields naturally +== Usage + +=== User interfaces This can be used in a UI to group or filter fields by their business entity. It can be more natural to group them by business entity than to group them by XML structure node. In that case the fields can be first sorted by business entity and second by alphabetical order. -==== Hardcoded identifiers +=== Hardcoded identifiers -Some identifiers like for example "PROCEDURE" were not present in the SDK except in the "pattern" of some fields. +Some identifiers like for example `PROCEDURE` were not present in the SDK except in the `pattern` of some fields. These identifiers are made of fixed text, in the business entities they have `"formatName"` with value `"fixedText"`. The identifier value is given by the `"text"`, for example `"text" : "PROCEDURE"`. -==== Detecting changes +=== Detecting changes The process of detecting changes could be automated inside of applications. In order to populate the data of the field `BT-13716-notice` the following logic can be used: * If the data of a field was changed -* Read the "businessEntityId" of the field via `fields.json` +* Read the `businessEntityId` of the field via `fields.json` * Get the business entity by business entity id via `fields.json` After this there are two cases. -===== Fixed identifiers +==== Fixed identifiers The simplest case is if the business entity has the fixed identifier format `fixedText`. In that case the `text` gives the identifier that changed. -===== Prefixed identifiers +==== Prefixed identifiers A more complex case is when the identifier has the prefixed number format `prefixedNumber`. -In that case the "instanceIdentifier" field can be found via the business entity. +In that case the `instanceIdentifier` field can be found via the business entity. The field business entity id of a field always points to the most precise business entity. But if the field is repeatable the application must pick the correct instance, the one to which the changed field belongs. -=== Usage in XML generation +=== XML generation and schemeName attribute In simple cases fields of type `id-ref` can only reference one type of identifier, in that case the scheme name is given. But in some cases for fields of type `id-ref` the user can select between multiple identifier types. For example `ORG` or `TPO`, this means the user will decide the `schemeName`, it cannot be determined in advance. + Assuming the user selected `Touch point one (TPO-0001)`: * The application puts the correct id `TPO-0001` into the field From 3fa50b2de1cd178157788f6df27d0952835f7459 Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Mon, 22 Jan 2024 18:10:11 +0100 Subject: [PATCH 04/10] TEDEFO-2944 adapting the business entities docs to the recent changes, adding schemeNames, added repeatsWithNodeId. --- modules/fields/pages/business-entities.adoc | 22 ++++++++++----------- modules/fields/pages/index.adoc | 11 ++++++----- modules/fields/pages/xml-structure.adoc | 4 +++- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc index 663230cf..4ab08139 100644 --- a/modules/fields/pages/business-entities.adoc +++ b/modules/fields/pages/business-entities.adoc @@ -29,8 +29,8 @@ The information about identifiers was spread across the fields, nodes and patter To solve this we decided to add what we call "business entities" to the SDK. We also decided that each field should belong to one and only one business entity. -The business entities are independent from the XML structure (nodes). -Thus in `fields.json` the fields have a `businessEntityId` and we decided that nodes of the `xmlStructure` would have none. +The business entities are independent from the XML structure (nodes) even if there are common points. +Thus in `fields.json` the fields have a `businessEntityId` and we decided that nodes of the `xmlStructure` nodes would only have a business entity if repeatable. The business entities describe what we call the logical structure. @@ -44,17 +44,18 @@ Business entities are provided as a JSON array called `businessEntities` in the `name`:: A short name which can be used for display (instead of the id). `description`:: A descriptive text, it is longer than the `name`. `repeatable`:: Indicates if the business entity can be repeated inside its parent. -`schemeName`:: Indicates the schemeName (if applicable). +`repeatsWithNodeId`:: Indicates the node the business entity repeats with, present if it repeats. `identifierFieldId`:: Indicates which field id identifies this business entity instance (if applicable). `captionFieldId`:: Indicates which field id can be used to display this business entity instance to a user (if applicable). `instanceIdentifier`:: An object to document the instance identifier (if applicable). `formatName`:: Found in `instanceIdentifier`, the format name, for now we have two, the "prefixedNumber" or "fixedText". `text`:: Found in `instanceIdentifier`, the identifier prefix or the fixed text. +`schemeName`:: Indicates the schemeName (if applicable). == Legacy data -The business entities make some of the `fields.json` data obsolete. -We will keep this data for backward compatibility reasons, it could be removed in a future SDK. +The business entities could make some of the `fields.json` data obsolete. +We will keep this data for backward compatibility reasons, but it could be removed in a future SDK. For example: @@ -62,14 +63,13 @@ For example: ---- "businessEntityId" : "groupOfLots", "idScheme" : "GLO", - "schemeName" : "LotsGroup", + ... + "schemeName" : "LotsGroup", ---- The field `schemeName` is coming from the business entity, it should ideally be retrieved via the business entity of the field. -We will keep this `schemeName` in the `fields.json`. -The same is true for the `idScheme`. - -There are similar cases for the nodes `identifierFieldId` and `captionFieldId`, both of which are provided by the business entities but the relationship is more indirect. +We will keep the `schemeName` in the `fields.json` for backward compatibility. +The same is true for the `idScheme`, `identifierFieldId` and `captionFieldId`. == Usage @@ -94,7 +94,7 @@ In order to populate the data of the field `BT-13716-notice` the following logic * Read the `businessEntityId` of the field via `fields.json` * Get the business entity by business entity id via `fields.json` -After this there are two cases. +After this there are two cases fixed and prefixed identifiers. ==== Fixed identifiers diff --git a/modules/fields/pages/index.adoc b/modules/fields/pages/index.adoc index 0ffbc799..4ccd6324 100644 --- a/modules/fields/pages/index.adoc +++ b/modules/fields/pages/index.adoc @@ -177,7 +177,8 @@ The various characteristics of each field are indicated as properties of the JSO "type" : "id-ref", "attributes" : [ "BT-13714-Tender-Scheme" ], "businessEntityId" : "tender", - "idSchemes" : [ "LOT", "GLO" ], // <18> + "idSchemes" : [ "GLO", "LOT" ], // <18> + "schemeNames" : [ "LotsGroup", "Lot" ], // <19> "legalType" : "IDENTIFIER", "repeatable" : { "value" : false, @@ -215,7 +216,7 @@ Applicable only for fields of type "code". <16> This property provides information on when a field's value is mandatory. <17> A RegEx pattern the field's value must match. <18> Array indicating the valid `idScheme` values which this identifier reference field (`"type" : "id-ref"`) can reference. - +<19> Array indicating the valid `schemeName` values which this identifier reference field (`"type" : "id-ref"`) can reference. === Property Values @@ -241,6 +242,7 @@ The properties that are assigned with static values are listed below: `businessEntityId`:: The id of the business entity the field belongs to. See xref:fields:business-entities.adoc[Business Entities]. `idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of valid identifier schemes that this `id-ref` field can reference. `idScheme`:: Applicable only to fields of type `id`. Indicates the identifier scheme for this `id` field (e.g. "TPO" for Touch Point). +`schemeNames`:: Applicable only to fields of type `id-ref`. Provides an array of valid scheme names that this `id-ref` field can reference. `schemeName`:: Applicable only to fields of type `id`. Indicates the value that should be indicated for this field in the `schemeName` attribute in the XML. `legalType`:: The data type of the Business Term associated with the field as defined by the eForms Regulation. `maxLength`:: The maximum number of characters that the field can hold. @@ -482,8 +484,8 @@ This expression is made of two parts: The possible technical values for a field type are: [horizontal] -`id`:: string representing an identifier (may have an associated `idScheme`) -`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes`) +`id`:: string representing an identifier (may have an associated `idScheme` and `schemeName`) +`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes` and `schemeNames`) `indicator`:: boolean (true or false) `integer`:: whole-valued positive number `number`:: numerical value, with optional decimal places. @@ -498,4 +500,3 @@ The possible technical values for a field type are: `text`:: language-independent string `text-multilingual`:: string that can be translated into multiple languages - diff --git a/modules/fields/pages/xml-structure.adoc b/modules/fields/pages/xml-structure.adoc index 404cb7b6..11a44867 100644 --- a/modules/fields/pages/xml-structure.adoc +++ b/modules/fields/pages/xml-structure.adoc @@ -44,7 +44,8 @@ The following snippet shows the information provided for each node. "xpathRelative" : "cac:ProcurementProjectLot[cbc:ID/@schemeName='Lot']", // <4> "repeatable" : true, // <5> "identifierFieldId" : "BT-137-Lot", // <6> - "captionFieldId" : "BT-21-Lot" // <7> + "captionFieldId" : "BT-21-Lot", // <7> + "businessEntityId" : "lot" // <8> } ---- <1> Identifier of the node. @@ -54,6 +55,7 @@ The following snippet shows the information provided for each node. <5> Indicates if the node can be repeated inside its parent. <6> Indicates the field of type `id` that identifies specific instances of this node, only present if applicable. <7> Indicates the field that can be used to help a user recognise a specific instance of this node, like a name or title. Only present if applicable. +<8> Indicates the business entity this node repeats with, present if repeatable. The absolute XPath of a node can be constructed from the XPaths of its parent and successive ancestors. We provide it for each node as a convenience. From 94954ea01fb8511570a8b4174c460fbce8716da7 Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Wed, 24 Jan 2024 10:56:26 +0100 Subject: [PATCH 05/10] TEDEFO-2944 removing parent as we decided to not have it for now. --- modules/fields/pages/business-entities.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc index 4ab08139..dd5a853b 100644 --- a/modules/fields/pages/business-entities.adoc +++ b/modules/fields/pages/business-entities.adoc @@ -40,10 +40,9 @@ Business entities are provided as a JSON array called `businessEntities` in the [horizontal] `id`:: Identifier of the business entity. -`parentId`:: Identifier of the direct parent business entity (if applicable). `name`:: A short name which can be used for display (instead of the id). `description`:: A descriptive text, it is longer than the `name`. -`repeatable`:: Indicates if the business entity can be repeated inside its parent. +`repeatable`:: Indicates if the business entity can be repeated. `repeatsWithNodeId`:: Indicates the node the business entity repeats with, present if it repeats. `identifierFieldId`:: Indicates which field id identifies this business entity instance (if applicable). `captionFieldId`:: Indicates which field id can be used to display this business entity instance to a user (if applicable). From 50cc197514f4e8ea39975b5ba7ba7dfc1f047e5a Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Wed, 7 Feb 2024 10:19:12 +0100 Subject: [PATCH 06/10] TEDEFO-2944 replacing schemeNames by referencedBusinessEntityIds. --- modules/fields/pages/index.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/fields/pages/index.adoc b/modules/fields/pages/index.adoc index 4ccd6324..b8979226 100644 --- a/modules/fields/pages/index.adoc +++ b/modules/fields/pages/index.adoc @@ -178,7 +178,7 @@ The various characteristics of each field are indicated as properties of the JSO "attributes" : [ "BT-13714-Tender-Scheme" ], "businessEntityId" : "tender", "idSchemes" : [ "GLO", "LOT" ], // <18> - "schemeNames" : [ "LotsGroup", "Lot" ], // <19> + "referencedBusinessEntityIds" : [ "groupOfLots", "lot" ], // <19> "legalType" : "IDENTIFIER", "repeatable" : { "value" : false, @@ -242,7 +242,7 @@ The properties that are assigned with static values are listed below: `businessEntityId`:: The id of the business entity the field belongs to. See xref:fields:business-entities.adoc[Business Entities]. `idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of valid identifier schemes that this `id-ref` field can reference. `idScheme`:: Applicable only to fields of type `id`. Indicates the identifier scheme for this `id` field (e.g. "TPO" for Touch Point). -`schemeNames`:: Applicable only to fields of type `id-ref`. Provides an array of valid scheme names that this `id-ref` field can reference. +`referencedBusinessEntityIds`:: Applicable only to fields of type `id-ref`. Provides an array of business entities that this `id-ref` field can reference. `schemeName`:: Applicable only to fields of type `id`. Indicates the value that should be indicated for this field in the `schemeName` attribute in the XML. `legalType`:: The data type of the Business Term associated with the field as defined by the eForms Regulation. `maxLength`:: The maximum number of characters that the field can hold. @@ -485,7 +485,7 @@ The possible technical values for a field type are: [horizontal] `id`:: string representing an identifier (may have an associated `idScheme` and `schemeName`) -`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes` and `schemeNames`) +`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes` and `referencedBusinessEntities`) `indicator`:: boolean (true or false) `integer`:: whole-valued positive number `number`:: numerical value, with optional decimal places. From e0a617d329b1da6ee41b722bebaac162e825f458 Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Wed, 7 Feb 2024 14:08:20 +0100 Subject: [PATCH 07/10] TEDEFO-2944 fix of referencedBusinessEntities to referencedBusinessEntityIds. --- modules/fields/pages/index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/fields/pages/index.adoc b/modules/fields/pages/index.adoc index b8979226..6d4c76e3 100644 --- a/modules/fields/pages/index.adoc +++ b/modules/fields/pages/index.adoc @@ -485,7 +485,7 @@ The possible technical values for a field type are: [horizontal] `id`:: string representing an identifier (may have an associated `idScheme` and `schemeName`) -`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes` and `referencedBusinessEntities`) +`id-ref`:: string representing a reference to an identifier (has an associated `idSchemes` and `referencedBusinessEntityIds`) `indicator`:: boolean (true or false) `integer`:: whole-valued positive number `number`:: numerical value, with optional decimal places. From 56fbeb1aa8c95786379744957b6b4b6a1c115ccb Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Thu, 8 Feb 2024 12:24:21 +0100 Subject: [PATCH 08/10] TEDEFO-2944 adding indication about deprecation of idSchemes and replacement by referencedBusinessEntityIds. --- modules/fields/pages/index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/fields/pages/index.adoc b/modules/fields/pages/index.adoc index 6d4c76e3..7ff368d6 100644 --- a/modules/fields/pages/index.adoc +++ b/modules/fields/pages/index.adoc @@ -240,7 +240,7 @@ The properties that are assigned with static values are listed below: `attributes`:: An array of one or more identifiers of the fields representing the XML attributes the XML element represented by the field can have. `presetValue`:: The value used to pre-fill a field. This property is always a string, but the value should be converted to the same type as the field. The value "\{NOW\}" corresponds to the current date or time. `businessEntityId`:: The id of the business entity the field belongs to. See xref:fields:business-entities.adoc[Business Entities]. -`idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of valid identifier schemes that this `id-ref` field can reference. +`idSchemes`:: Applicable only to fields of type `id-ref`. Provides an array of "prefixedNumber" identifier schemes that this `id-ref` field can reference (this will be deprecated later, referencedBusinessEntityIds should be used as it has more complete data). `idScheme`:: Applicable only to fields of type `id`. Indicates the identifier scheme for this `id` field (e.g. "TPO" for Touch Point). `referencedBusinessEntityIds`:: Applicable only to fields of type `id-ref`. Provides an array of business entities that this `id-ref` field can reference. `schemeName`:: Applicable only to fields of type `id`. Indicates the value that should be indicated for this field in the `schemeName` attribute in the XML. From 071b79efd34d303640a7651f64178364da98776b Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Tue, 27 Feb 2024 18:21:03 +0100 Subject: [PATCH 09/10] TEDEFO-2944 adapting the documentation to the latest changes done via 3173. --- modules/fields/pages/business-entities.adoc | 68 ++++++++++----------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/modules/fields/pages/business-entities.adoc b/modules/fields/pages/business-entities.adoc index dd5a853b..4bbd14cb 100644 --- a/modules/fields/pages/business-entities.adoc +++ b/modules/fields/pages/business-entities.adoc @@ -2,7 +2,8 @@ == Introduction -In some fields there are patterns like: +Here we will cover historical reasons for the addition of the business entities to the SDK. +In some fields there was a pattern like: [source,json] ---- @@ -22,15 +23,15 @@ Or this pattern: } ---- -Values like `LOT` are described in various places outside of the pattern. -But some values like `PROCEDURE` only existed in the SDK. +Values like `LOT` are described in the SDK in various places outside of the pattern. +But some values like `PROCEDURE`, `BUYER` only existed in these patterns. This gave us a hint that machine readable information was missing somewhere in the SDK. -The information about identifiers was spread across the fields, nodes and patterns. +Also information about identifiers was spread across the fields, nodes and patterns, nothing centralised this information. To solve this we decided to add what we call "business entities" to the SDK. We also decided that each field should belong to one and only one business entity. The business entities are independent from the XML structure (nodes) even if there are common points. -Thus in `fields.json` the fields have a `businessEntityId` and we decided that nodes of the `xmlStructure` nodes would only have a business entity if repeatable. +In `fields.json` the fields have a `businessEntityId` and we decided that nodes of the `xmlStructure` nodes would only have a business entity if repeatable. The business entities describe what we call the logical structure. @@ -38,20 +39,25 @@ The business entities describe what we call the logical structure. Business entities are provided as a JSON array called `businessEntities` in the `fields.json` -[horizontal] -`id`:: Identifier of the business entity. -`name`:: A short name which can be used for display (instead of the id). -`description`:: A descriptive text, it is longer than the `name`. -`repeatable`:: Indicates if the business entity can be repeated. -`repeatsWithNodeId`:: Indicates the node the business entity repeats with, present if it repeats. -`identifierFieldId`:: Indicates which field id identifies this business entity instance (if applicable). -`captionFieldId`:: Indicates which field id can be used to display this business entity instance to a user (if applicable). -`instanceIdentifier`:: An object to document the instance identifier (if applicable). -`formatName`:: Found in `instanceIdentifier`, the format name, for now we have two, the "prefixedNumber" or "fixedText". -`text`:: Found in `instanceIdentifier`, the identifier prefix or the fixed text. -`schemeName`:: Indicates the schemeName (if applicable). - -== Legacy data +* `id` Identifier of the business entity. +* `name` A short name which can be used for display (instead of the id). +* `description` A descriptive text, it is longer than the `name`. +* `repeatable` Indicates if the business entity can be repeated. +* `repeatsWithNodeId` Indicates the node the business entity repeats with, present if it repeats. + +* `changeIdentification` An object to document the what should be done when something changed in the business entity. +** `identifyInChangeNotice` A boolean to determine if a change in this business entity should be reported +** `useInstanceIdentifier` A boolean to determine if the instanceIdentifier should be used +** `changeIdentifier` A string to use to identify the change, if present it should be used + +* `instanceIdentifier` An object containing instance identifier information (if applicable). +** `referencedBusinessEntityId` A referenced business entity identifier, if present it means this business entity relies on another business entity for the identifiers. +** `prefix` Found in `instanceIdentifier`, the identifier prefix. +** `schemeName` Indicates the scheme name (if applicable). +** `identifierFieldId` Indicates which field id identifies this business entity instance (if applicable). +** `captionFieldId` Indicates which field id can be used to display this business entity instance to a user (if applicable). + +== Future The business entities could make some of the `fields.json` data obsolete. We will keep this data for backward compatibility reasons, but it could be removed in a future SDK. @@ -78,12 +84,6 @@ This can be used in a UI to group or filter fields by their business entity. It can be more natural to group them by business entity than to group them by XML structure node. In that case the fields can be first sorted by business entity and second by alphabetical order. -=== Hardcoded identifiers - -Some identifiers like for example `PROCEDURE` were not present in the SDK except in the `pattern` of some fields. -These identifiers are made of fixed text, in the business entities they have `"formatName"` with value `"fixedText"`. -The identifier value is given by the `"text"`, for example `"text" : "PROCEDURE"`. - === Detecting changes The process of detecting changes could be automated inside of applications. @@ -92,20 +92,14 @@ In order to populate the data of the field `BT-13716-notice` the following logic * If the data of a field was changed * Read the `businessEntityId` of the field via `fields.json` * Get the business entity by business entity id via `fields.json` +* Read the `identifyInChangeNotice` boolean -After this there are two cases fixed and prefixed identifiers. - -==== Fixed identifiers - -The simplest case is if the business entity has the fixed identifier format `fixedText`. -In that case the `text` gives the identifier that changed. - -==== Prefixed identifiers +After this there are several scenarios. -A more complex case is when the identifier has the prefixed number format `prefixedNumber`. -In that case the `instanceIdentifier` field can be found via the business entity. -The field business entity id of a field always points to the most precise business entity. -But if the field is repeatable the application must pick the correct instance, the one to which the changed field belongs. +* If `identifyInChangeNotice` is false, then do nothing. +* If `identifyInChangeNotice` is true: +** If `useInstanceIdentifier` is true, then the identifier of the modified instance must be found via the `instanceIdentifier` +** If `useInstanceIdentifier` is false, then the `changeIdentifier` gives the identifier that changed === XML generation and schemeName attribute From 36d051f11eadd576163aaa94da464239e01f58de Mon Sep 17 00:00:00 2001 From: "ROUSSY Christophe (OP-EXT)" Date: Mon, 15 Apr 2024 16:37:23 +0200 Subject: [PATCH 10/10] TEDEFO-2944 adding business-entity asset type in the translations docs matrix. --- modules/translations/pages/index.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/translations/pages/index.adoc b/modules/translations/pages/index.adoc index a4bf5fcd..4f4c87e7 100644 --- a/modules/translations/pages/index.adoc +++ b/modules/translations/pages/index.adoc @@ -218,6 +218,7 @@ The `text` label-type is also used with the `auxiliary` asset type to provide so [cols=">1,^1,^1,^1,^1,^1,^1,^1"] |=== h| h| `name` h| `description` h| `hint` h| `when‑true` h| `when‑false` h|`text` h|`template` +h|`business‑entity` |X|X|X|||| h|`business‑term` |X|X|X|||| h|`field` |X|X|X|||| h|`node` |X|X|X||||