Configure SmartPost ContactAddressSources

SmartPost uses a Contact Address Sources instance when a message is received from e-Boks, and the sender must be associated with the document (record) that is created at receipt of the SmartPost message. The connection between the message and the sender is made through addresses. The Contact Address Sources instance and its configuration point out the addresses that identify the sender and associate the sender with the document.

This topic describes the implementation and function of the Contact Address Sources instance and how to customize it by configuring or extending it.


Design

The diagram shows the core types which constitute the design of the Contact Address Source instance. The design complies to the factory design pattern.


Factory pattern implementation

IContactAddressSource is the interface that exposes the specific implementation of a Contact Address Source instance. The GetContactAddressKeys method will be called by the application, when a set of keys for addresses of the contacts is to be retrieved from a party identifier (CVR or CPR numbers). The OData service context is provided as a parameter to support the database access from the implementation.

ODataContactAddressSource is a concrete implementation of the IContactAddressSource interface. See ODataContactAddressSource for more details.

The ContactAddressSourceFactory can create instances, which implement the IContactAddressSource interface. The actual construction is done according to a configuration, which is described in Configuration of the GetContactAddressKeys method. The configuration is provided to the factory as an XML element.


Utility method (GetContactAddressKeys)

The application can ask the factory to provide a Contact Address Source instance, and then the application can use the Contact Address Source instance to retrieve the address keys that are related to a party identifier. The way contact addresses are retrieved varies depending on the party identifier type, for example CVR or CPR, and there it is useful to have at least one set of Contact Address Source instances per party identifier type where each can provide a set of address keys.

All this is contained in the static GetContactAddressKeys(PartyIdentifier, ODataService) method in the IdentifierSourceUtilities class.

Eksempel: Use of the GetContactAddressKeys method in the IdentifierSourceUtilities class


Configuration of the GetContactAddressKeys method

The method is configured by the XML specified in the Process settings in WorkZone Configuration Management (Operation > Process Settings) or in the WZP_SETTING entity named ContactAddressKeySources (the module name is “WorkZone”). This configuration is XML that is read and interpreted by the GetContactAddressKeys method, see Utility method (GetContactAddressKeys).

Eksempel: The standard configuration of the factory

The XML is interpreted as described below.

The following applies to the entire XML:

  • No name spaces are considered.
  • No schema is specified because the XML details are up to the actual implementations of the Contact Address Sources instance.

For the root element, the following rules applies:

  • The name of the root element is not important.
  • All attributes on the root element are ignored.

When the GetContactAddressKeys method is invoked, the XML is interpreted and the method is executed in the following way:

  1. Selection of child elements
  2. The child elements of the root element are searched for the element having an attribute named party-identifier-type, which is compared to identifier type (CVR or CPR) of the provided party identifier. The comparing is case insensitive. If the content of the party-identifier-type attribute matches the provided party identifier, then the child element is accepted. All other child elements are ignored.

  3. Creation of Contact Address Sources instance
  4. For each of the accepted child elements a Contact Address Source instance is created. See Configuration of a factory.

  5. Invocation of created Contact Address Sources instance
  6. When the instance has been created, the GetContactAddressKeys method is invoked, which returns a set of address keys. The set of address keys depends in the implementation.

  7. Collection of address keys
  8. Because several Contact Address Source instances can be created and invoked in the same call to the GetContactAddressKeys method in the IdentifierSourceUtilities class, several non-empty sets of address keys can be returned. The GetContactAddressKeys method collects the address keys contained in these sets in a System.Generic.Collections.HashSet<string>. In this way, it is ensured that the same address keys remain unique.

  9. The final result
  10. Finally, the GetContactAddressKeys method returns an enumeration of the collected address keys.


Configuration of a factory

As mentioned in section 2.3, the XML element (configuration element) that matches the requested party type is parsed to the factory, to make it produce a Contact Address Source instance. The factory does that by reading the class attribute from the configuration element. The value of the class attribute must be the fully qualified class name of the requested Contact Address Source implementation, and the class must implement the IContactAddressSource interface.

The factory then searches the class for a constructor, which matches one of the following signatures:

  • ctor(ODataService, XElement)
  • ctor(XElement, ODataService)
  • ctor(XElement)
  • ctor(ODataService)
  • ctor()

Where ODataService (FQCN = Scanjour.Process.OData.Client.Proxy.ODataService) is an OData access to the database and XElement (FQCN = System.Xml.Linq.XElement) is the XML element found by the factory.

The search is done in the shown order. Whenever a constructor is found, the parameters are provided and the constructor is called, so that the Contact Address Source instance is created and eventually returned by the factory.

The ODataService makes it possible for the Contact Address Source constructor to search additional information in the database.

The XElement can be used to retrieve implementation specific configuration to the constructor.


ODataContactAddressSource

The ODataContactAddressSource class is a general-purpose implementation of the IContactAddressSource interface.

The ODataContactAddressSource can access any register in the database that is made available through OData. The register, the query, and where the address keys values are located, are described below.

Configuration

The ODataContactAddressSource is configured by the XML element, which is provided by the factory. An example of an XML element for the ODataContactAddressSource.

Eksempel: A configuration example of the ODataContactAddressSource

The attributes on the contact-address-source are not used by the class, but have already been used by the factory. The XML element works more like a placeholder for the three inner XML elements.

It is the three inner XML elements, which configure the ODataContactAddressSource.

register-name

The name of the register on which the OData query will take offset.

query-template The template that is used to form the query. When the GetContactAddressKeys(PartyIdentifier, ODataService) method is invoked, then two empty curled braces ({}) will be replaced by the party identifier code, such as the actual CVR or CPR number, which is the first parameter to the method.
field-name The name of the field on the result, which content will be returned by the method. The field is expected to contain the address keys of the address entity, which is connected to the provided party identifier, for example ID.

The final OData query will be formed in the following way:

{base-uri}{register-name}{partial-query}

Where

{base-uri} is the URI to the data source – for example http://db01/OData/

{register-name} - The content of the register-name element, for example Addresses.

{partial-query} - The content of the query-template element after the curled braces has been replaced by the name key. For example, a query template can be:

?$filter=Name/NameCode eq '{}'&$select=ID

(Remember that & in XML must be written as &amp; - see Figure 4 for an example.)

If the party identifier code is ‘180582-3042’ then the {partial-query} will then be:

?$filter=Name/NameCode eq '180582-3042'&$select=ID

Taken the above examples the final query will be:

http://db01/OData?$filter=Name/NameCode eq '180582-3042'&$select=ID

From the result of the query, the ID of all the returned entities will be collected.


Customized implementation

If the provided ODataContactAddressSource is insufficient for making a specific customization, then a customized implementation will probably solve it.

To do so you must make an assembly containing your customized Contact Address Source. Add the assembly to the WorkZone Process package and change the configuration in WZP_SETTINGS, so that your class is used by the factory to create your Contact Address Source instance.

Follow these steps:

  1. Create a Class Library project for the purpose. Beware of dependencies to other projects.
  2. Make the project reference the WorkZone.Dispatcher.Base assembly.
  3. In your project create a file containing an empty class.
  4. Make your file use the WorkZone.Dispatcher.Base namespace.
  5. Make the class implement the IContactAddressSource-interface.
  6. Make a constructor to class that complies to one of the constructors described in Configuration of a factory.
  7. If required, then use the constructor to retrieve configuration information from the XML element or directly from the database using the ODataService provided.
  8. Implement the GetContactAddressKeys method, so it complies to the interface.
  9. Write tests that verifies your implementation.
  10. Compile and include your assembly in the WorkZone Process package.
  11. Change the configuration in WorkZone Configuration Management or WZP_SETTINGS so your new Contact Address Source is used by the correct party identifier type and so the constructor receives the correct XML element (if required).
  12. Use Visual Studio to generate a new assembly with an updated set of proxy classes. The content of the new assembly must take offset in your customized data dictionary.
  13. Make your installation substitute the existing assembly with the newly generated assembly. Do this by copying the new assembly to “C:\Program Files (x86)\KMD\WorkZone\Process\Web\Services\Bin"
  14. Make an IISRESET.
  15. Test your creation.