Tutorial - Create / Update File Package
The goal with this tutorial is to understand the create/update integration and how you could import a structure of Parts with attached Specifications having files.
We will see how the create-update integration can use ZIP files as input. The create/update integration will in this tutorial be invoked via a directory listener, but could easily have been supported via a REST call.
ZIP file content
The input ZIP file is assumed to follow this structure:
data.zip
├───data.xml
│
└───files
├───08b3608d-171c-439e-b233-100892036096
│ └───generic
│ └───Specification.pdf
│
└───889f20cd-8a7e-4855-9e3e-f137813e9d9d
└───generic
├───drawing-001.pdf
├───drawing-002.pdf
└───mounting-instructions.docx
On the root level, there is a data.xml
file that contains the meta-data for the objects and the connections between them.
The files folder holds the files. In this case, each document have its own UUID and this is used to group the files together with the file format.
Note that the structure does not have to follow this format, this is just an example. If you for example dont know what format the files uses in ENOVIA/3DEXPERIENCE then you probably will leave that directory out.
The data file format
The data.xml
file describes the meta-data of the objects and the relationships between these.
For this tutorial the data format as shown in the example below. It contains the Item’s along with their Specification and the structure.
<PackageData>
<Items>
<Item>
<Id>496693e2-8818-473a-b240-1ae6e5e4b091</Id>
<Type>Part</Type>
<Name>ASY-JG1</Name>
<Revision>A</Revision>
<Description>ASY-JG1</Description>
<Status>Create</Status>
<Weight>0.0</Weight>
<DesignPurchase>Make</DesignPurchase>
</Item>
<Item>
<Id>2cfc41e6-b0e1-4ee8-bfb6-6ef366f543d1</Id>
<Type>Part</Type>
<Name>THW-AHG-00011</Name>
<Revision>A</Revision>
<Description></Description>
<Status>Create</Status>
<Weight>520.0</Weight>
<DesignPurchase>Make</DesignPurchase>
</Item>
<Item>
<Id>889c9be0-f5e9-4327-b748-01db0b3c4bdf</Id>
<Type>Part</Type>
<Name>THW-YHG-69103</Name>
<Revision>A</Revision>
<Description></Description>
<Status>Create</Status>
<Weight>40.0</Weight>
<DesignPurchase>Make</DesignPurchase>
<Specifications> (1)
<Specification id="889f20cd-8a7e-4855-9e3e-f137813e9d9d" />
<Specification id="08b3608d-171c-439e-b233-100892036096" />
</Specifications>
</Item>
</Items>
<Structure>
<Item id="496693e2-8818-473a-b240-1ae6e5e4b091"> (2)
<Item id="2cfc41e6-b0e1-4ee8-bfb6-6ef366f543d1" pos="1" qty="1" />
<Item id="889c9be0-f5e9-4327-b748-01db0b3c4bdf" pos="2" qty="10" />
</Item>
</Structure>
<Specifications>
<Specification>
<Id>889f20cd-8a7e-4855-9e3e-f137813e9d9d</Id>
<Type>Functional Specification</Type>
<Name>SX-01-339-X-AS</Name>
<Revision>A</Revision>
<Title>Lorem ipsum</Title>
<Description>Foo bar</Description>
</Specification>
<Specification>
<Id>08b3608d-171c-439e-b233-100892036096</Id>
<Type>Functional Specification</Type>
<Name>Z98-77X89-A</Name>
<Revision>A</Revision>
<Title>Z98-77X89-A</Title>
<Description>....</Description>
</Specification>
</Specifications>
</PackageData>
1 | Item references its specifications by a UUID |
2 | Bill of materials structure defines the items only based upon their UUIDs. |
NOTE:
-
The specifications must be created prior to processing the items.
-
The items must be created before creating the connections between them.
The Create/Update configuration
On the TIF server we need to create our create/update configuration that defines how to create/update the business objects and connections in the ENOVIA/3DEXPERIENCE database, according to the input format.
In our case, the configuration will look like this:
<CreateConfiguration
txType="update"
runPrivileged="true"
historyOff="true"
triggerOff="true">
<InputFormats>
<Zip>
<InputFiles>data.xml</InputFiles> (1)
</Zip>
</InputFormats>
<EntryPoint
select="/PackageData/Specifications/Specification"
mode="create-documents" /> (2)
<EntryPoint
select="/PackageData/Items/Item"
mode="create-objects" /> (3)
<EntryPoint
select="/PackageData/Structure/Item"
mode="bill-of-materials" /> (4)
<ValueMapper id="design-purchase-mapping"> (5)
<If is="Buy">Purchase</If>
<If is="Make">Design</If>
</ValueMapper>
<!--+
| This configuration is used when to create or update
| all the specifications including checking in all files
| part of the ZIP file.
+-->
<Config match="Specification" mode="create-documents"> (6)
<IfFound>update</IfFound>
<IfNotFound>create</IfNotFound>
<IdentityMatch>
<Type select="Type/text()" />
<Name select="Name/text()" />
<Revision select="Revision/text()"/>
</IdentityMatch>
<CreateValues>
<Policy fallbackValue="policy_Specification"/>
<Vault fallbackValue="vault_eServiceProduction" />
</CreateValues>
<UpdateValues useForCreate="true">
<Description select="Description/text()"/>
<Attribute name="attribute_Title" select="Title/text()"/>
</UpdateValues>
<EmbeddedFiles>
<File reuseVersion="true"
formatFallback="generic"
useFileMapper="true"> (7)
<FileMapper>
<PathItem value="files" />
<PathItem select="Id/text()" />
<PathItem mapsToFormat="true" />
</FileMapper>
</File>
</EmbeddedFiles>
</Config>
<Config match="Item" mode="create-objects"> (8)
<IfFound>update</IfFound>
<IfNotFound>create</IfNotFound>
<IdentityMatch>
<Type select="Type/text()" />
<Name select="Name/text()" />
<Revision select="Revision/text()"/>
</IdentityMatch>
<CreateValues>
<Policy fallbackValue="policy_DevelopmentPart"/>
<Vault fallbackValue="vault_eServiceProduction" />
</CreateValues>
<UpdateValues useForCreate="true">
<Description select="Description/text()"/>
<Attribute name="attribute_Weight" select="Weight/text()"/>
<Attribute
name="attribute_DesignPurchase"
valueMapper="design-purchase-mapping"
select="DesignPurchase/text()"/>
</UpdateValues>
<Connections>
<Connection relationship="relationship_ReferenceDocument"
select="Specifications/Specification"
mode="connect-specifications"
disconnectExisting="false"> (9)
<IdentityMatch>
<Object>
<Name select="/PackageData/Specifications/Specification[./Id/text() = current()/@id]/Name/text()" />
</Object>
</IdentityMatch>
</Connection>
</Connections>
</Config>
<!--+
| This configuration is used when to find a specifications
| to connect with in the context when creating items.
+-->
<Config match="Specification" mode="connect-specifications"> (10)
<IfFound>ignore</IfFound>
<IfNotFound>fail</IfNotFound>
<IdentityMatch> (11)
<Type select="/PackageData/Specifications/Specification[./Id/text() = current()/@id]/Type/text()" />
<Name select="/PackageData/Specifications/Specification[./Id/text() = current()/@id]/Name/text()" />
<Revision select="/PackageData/Specifications/Specification[./Id/text() = current()/@id]/Revision/text()" />
</IdentityMatch>
</Config>
<Config match="Item" mode="bill-of-materials"> (12)
<IfFound>update</IfFound>
<IfNotFound>fail</IfNotFound>
<IdentityMatch> (13)
<Type select="/PackageData/Items/Item[./Id/text() = current()/@id]/Type/text()" />
<Name select="/PackageData/Items/Item[./Id/text() = current()/@id]/Name/text()" />
<Revision select="/PackageData/Items/Item[./Id/text() = current()/@id]/Revision/text()" />
</IdentityMatch>
<Connections>
<Connection relationship="relationship_EBOM"
select="Item"
mode="bill-of-materials"
disconnectExisting="false"> (14)
<IdentityMatch>
<Relationship>
<Attribute name="attribute_FindNumber" select="@pos"/>
</Relationship>
</IdentityMatch>
<UpdateValues>
<Attribute name="attribute_Quantity" select="@qty" />
</UpdateValues>
</Connection>
</Connections>
</Config>
</CreateConfiguration>
1 | Specify that we will read the data from a ZIP file, and the data files are named data.xml in the root level. |
2 | We need to create the documents first, and this entry point specifies the elements to process and in what mode.
It will be mapped to the corresponding <Config> element defined later. |
3 | Specifies the items to be processed |
4 | Specifies the item structure (bill of materials) to be processed |
5 | Inlined value mapping to translate values from the incoming data into ENOVIA/3DEXPERIENCE accepted values. |
6 | Configuration used for creating or updating the documents. |
7 | File checkin configuration. Here we specify that we will map the files from the incoming ZIP archive into the object, and we use the UUID identifier on the object to map the folder. The last folder defines the format of the file. |
8 | Configuration used for creating or updating the items |
9 | Specifies how to connect the specifications and how we identify the Specification object. |
10 | The configuration used when to connect the item with the specification. This configuration is only used to actually find the object in the database, hence only the identity match is defined, and we expect the object to actually exist otherwise it is a failure. |
11 | In the incoming XML data we only have a UUID reference to the specification, hence we need to use an XPath construct that allows us to find the actual Specification element holding the database identifiers. |
12 | The configuration used when creating the bill of materials structure. |
13 | Since the information in the XML data only specifies the UUID identifiers, we need to lookup the actual items by using slightly more complicated XPath constructs. |
14 | The connect specification for EBOM relationships uses the Find Number mapped to the pos attribute to identifying relationships |
Key takeaways:
-
In case you process elements with the same but with different purposes, then use the "mode" setting to distinguish the different configurations.
The directory listener
Finally, in order to be able to use the file package import utility, we need to setup the directory listener.
We want to allow someone to drop a ZIP package into the directory /mnt/bom-package/in
.
In the file ${TIF_ROOT}/modules/enovia/cfg/directorylistener/BOMPackageImport.xml
add this
<tif:DirectoryListener
xmlns:tif="http://technia.com/TIF/DirectoryListener"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://technia.com/TIF/DirectoryListener http://products.technia.com/tif/schema/latest/DirectoryListener.xsd">
<tif:Name>Import BOM Package via File</tif:Name>
<tif:WithContext user="IntegrationAgent" /> (1)
<tif:Paths>
<tif:Input>/mnt/bom-package/in</tif:Input> (2)
<tif:Output>/mnt/bom-package/out</tif:Output>
<tif:Error>/mnt/bom-package/err</tif:Error>
</tif:Paths>
<tif:Handler type="CreateUpdateIntegration" /> (3)
<tif:Arguments>
<tif:Argument name="configuration" value="tvc:createconfig/BOMPackageImport.xml" /> (4)
</tif:Arguments>
</tif:DirectoryListener>
1 | Specify what user to run DB calls in ENOVIA/3DEXPERIENCE as |
2 | Configure input directory |
3 | Specify that we are using the CreateUpdateIntegration handler |
4 | As argument, we need to provide the create update configuration and we point out the previous config we made |
The directory listener will after processing create a file with the same name as your input file, in the configured output directory, containing the result of the operation.
If any error happens, a file with the same name as the input file will be created in the error directory, containing error information.