Class ObjectMapper
- java.lang.Object
-
- com.avoka.tm.util.ObjectMapper
-
public class ObjectMapper extends java.lang.Object
This class provides XML Document to Object mapping support.
Transact supports marshalling data between Form XML Documents and Groovy Value Objects using the ObjectMapper class. Where possible we recommend you use the ObjectMapper for mashalling data, rather the doing this by hand which is tedious and often error prone.
The ObjectMapper supports two use cases:
- creating an Groovy object graph from an XML document
- updating an XML document based on an Groovy object graph
ObjectMapper Configuration
The ObjectMapper has a number of default configurations, which can be changed with the appropriate setter methods:
-
strictMode
- specified whether a missing Object field for aDocument
tag will throw an exception (default valuetrue
).
Note: Disabling strict mode may bring some unpredictable behavior especially with repeats when there is total mismatch of the object and XML structure. The result could be wrong mapping of XML tags and values to objects. -
mappingStrategy
- specifies XML tag name to object mapping strategy (default valueCamelUpperCase
). For example '<FirstName>' XML tag will map toObject
's field 'firstName'. dateFormat
- the date time mashalling format (default value of 'yyyy-MM-dd').
The example below set mapping strategy to handle XML Document's tag of type 'lowerCamelCase', date format 'yyyy/dd/MM' and switch off the strict mapping mode (ignore unknown XML tag and not throw an exception).
import com.avoka.tm.util.* import java.text.SimpleDateFormat new ObjectMapper() .setMappingStrategy(MappingStrategy.LOWER_CAMEL_CASE) .setDateFormat(new SimpleDateFormat("yyyy/dd/MM")) .setStrictMode(false)
Groovy Examples
Please find the ObjectMapper examples below using the following Groovy value object classes.
package com.maguire.vo import java.util.* class Person { String firstName String lastName String email Address currentAddress List<Address> previousAddresses } class Address { String line1 String city Integer postCode String country }
The corresponding XML elements for these classes are provided below
<Person> <FirstName/> <LastName/> <Email/> <CurrentAddress> <Line1/> <City/> <PostCode/> <Country/> </CurrentAddress> <PreviousAddresses> <Address> <Line1/> <City/> <PostCode/> <Country/> </Address> </PreviousAddresses> </Person>
Creating an Object Graph
This Groovy example creates Person object from Document's xpath.
import com.avoka.tm.util.* import com.maguire.vo.* Person person = new ObjectMapper() .setDoc(param.appDoc) .setFormXPath('/Person') .create(Person.class)
An example source XML document is provided below. In this example the XML repeating
PreviousAddresses
elements will be mapped into the Person classesList<Address> previousAddresses
field.<?xml version="1.0"?> <AvokaSmartForm> <Person> <FirstName>John</FirstName> <LastName>Smith</LastName> <Email>jsmith@maguire.com</Email/> <CurrentAddress> <Line1>12 Peterson Avenue</Line1> <City>Hope Town</City> <PostCode>4275</PostCode> <Country/> </CurrentAddress> <PreviousAddresses> <Address> <Line1>30 Peace Street</Line1> <City>Hope Town</City> <PostCode>4276</PostCode> <Country/> </Address> <Address> <Line1>Unit 3/65 Dunkley Avenue</Line1> <City>Melville</City> <PostCode>5621</PostCode> <Country>Australia<Country> </Address> </PreviousAddresses> </Person> <AvokaSmartForm>
Repeats Support
This Groovy example shows how to map object's repeat field with XML tag.
In order to enable repeat support the repeat field (e.g.
List<Address> previousAddresses
) needs those two annotations:JacksonXmlElementWrapper
, which allows specifying XML element to use for wrapping, andJacksonXmlProperty
, which allows specifying XML local element name for a property
package com.maguire.vo import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import java.util.* class Person { String firstName String lastName String email Address currentAddress @JacksonXmlElementWrapper(localName = "PreviousAddresses") @JacksonXmlProperty(localName = "Address") List<Address> previousAddresses } class Address { String line1 String city Integer postCode String country }
An example source XML document is provided below.
In this example, the XML repeating
Address
elements of the wrapperPreviousAddresses
element will be mapped into the Person classesList<Address> previousAddresses
field and each child nodeAddress
will createAddress
object and add to theList<Address> previousAddresses
.<?xml version="1.0"?> <AvokaSmartForm> <Person> <FirstName>John</FirstName> <LastName>Smith</LastName> <Email>jsmith@maguire.com</Email/> <CurrentAddress> <Line1>12 Peterson Avenue</Line1> <City>Hope Town</City> <PostCode>4275</PostCode> <Country/> </CurrentAddress> <PreviousAddresses> <Address> <Line1>30 Peace Street</Line1> <City>Hope Town</City> <PostCode>4276</PostCode> <Country/> </Address> <Address> <Line1>Unit 3/65 Dunkley Avenue</Line1> <City>Melville</City> <PostCode>5621</PostCode> <Country>Australia<Country> </Address> </PreviousAddresses> </Person> <AvokaSmartForm>
Important remarks when working with repeats:
- Root element must be a POJO but can not be a repeat
- Refrain from disabling strict mode as it may bring some unpredictable behavior especially when there is total mismatch of the object and XML structure. The result could be wrong mapping of XML tags and values to objects.
Updating XML Document
This Groovy example stores Person object in the Document using the XPath '/Person'. Please note the ObjecMapper will automatically set the appropriate root XPath based on the type of document.
import com.avoka.tm.util.* import com.maguire.vo.* Person person = new Person() person.firstName = 'Peter' new ObjectMapper() .setObject(person) .setFormXPath('/Person') .update(param.appDoc)
Object Map Field Support
Support is also provided for Object map fields. This feature is very useful for mapping adhoc XML elements into a class Object.
The example below has added
Map
customProps field.package com.maguire.vo import java.util.* class Person { String firstName String lastName String emailAddress Map<String, String> customProps }
XML of Primary Applicant's 'customProps' could be properties like account number, tax number, etc.
<Person> <CustomProps> <accountNumber>12345</accountNumber> <taxNumber>67890</taxNumber> </CustomProps> </Person>
import com.avoka.tm.util.* import com.maguire.vo.* Person person = new ObjectMapper() .setDoc(param.appDoc) .setFormXPath('/Person') .create(Person.class) String accountNumber = person.customProps.get('accountNumber') // May put new property value and use update...
Transact Function Example
The function example below is creating an new Applicant object graph from the application document (
param.appDoc
).The example then updating the applicants address details, and then write the object graph back into the application document. Finally in the
FormFuncResult
result we turn on the option to return the form XML document back to the form. The JavaScript form application will then update its model with the new address details and display them to the user.package com.maguire.svc; import com.avoka.tm.func.* import com.avoka.tm.svc.* import com.avoka.tm.util.* import com.avoka.tm.vo.* import com.maguire.vo.* import javax.servlet.http.* public class Controller { // Injected at runtime public Logger logger FuncResult invoke(FuncParam param) { // Marshal formData into applicant object VO graph Person applicant = new ObjectMapper() .setDoc(param.appDoc) .setFormXPath("/Applicant") .create(Person.class) logger.info("Applicant: " + applicant) // Add applicant address information applicant.currentAddress = new Address() applicant.currentAddress.line1 = "61 Main Street" applicant.currentAddress.city = "Avalon" applicant.currentAddress.postCode = "2107" applicant.currentAddress.country = "Australia" // Update formData with updated application object new ObjectMapper() .setObject(applicant) .setFormXPath("/Applicant") .update(param.appDoc) FormFuncResult result = new FormFuncResult() // Specify formData to be returned to form result.includeFormData = true return result } }
The examples XML response document is provided below. Note in this example we have mapped the Person objects into the documents Applicant element.
<?xml version="1.0"?> <AvokaSmartForm> <Applicant> <FirstName>John</FirstName> <LastName>Smith</LastName> <Email>jsmith@maguire.com</Email/> <CurrentAddress> <Line1>61 Main Street</Line1> <City>Avalon</City> <PostCode>2107</PostCode> <Country>Australia</Country> </CurrentAddress> <PreviousAddresses/> </Applicant> <AvokaSmartForm>
- Since:
- 17.10.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
ObjectMapper.MappingStrategy
Naming convention mapping strategy enumeration.
-
Constructor Summary
Constructors Constructor Description ObjectMapper()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description <T> T
create(java.lang.Class<T> type)
Create object of the generic T type.ObjectMapper
setDateFormat(java.text.DateFormat dateFormat)
Set date format.ObjectMapper
setDoc(org.w3c.dom.Document document)
Set document object to create object from.ObjectMapper
setFormXPath(java.lang.String xpath)
Set the Form XPath parameter.ObjectMapper
setMappingStrategy(ObjectMapper.MappingStrategy mappingStrategy)
Set mapping strategy.ObjectMapper
setObject(java.lang.Object object)
Set object to update.ObjectMapper
setStrictMode(boolean strict)
Set strict mapping mode.ObjectMapper
setXPath(java.lang.String xpath)
Set the explicit XPath parameter.void
update(org.w3c.dom.Document document)
Update object of the generic T type.
-
-
-
Method Detail
-
setDateFormat
public ObjectMapper setDateFormat(java.text.DateFormat dateFormat)
Set date format. If not specified the default 'yyyy-MM-dd' date pattern will be used.- Parameters:
dateFormat
- date format- Returns:
- object mapper object
-
setDoc
public ObjectMapper setDoc(org.w3c.dom.Document document)
Set document object to create object from.- Parameters:
document
- document object to create object from- Returns:
- object mapper object
-
setMappingStrategy
public ObjectMapper setMappingStrategy(ObjectMapper.MappingStrategy mappingStrategy)
Set mapping strategy.- Parameters:
mappingStrategy
- mapping strategy- Returns:
- object mapper object
-
setObject
public ObjectMapper setObject(java.lang.Object object)
Set object to update.- Parameters:
object
- object to update- Returns:
- object mapper object
-
setStrictMode
public ObjectMapper setStrictMode(boolean strict)
Set strict mapping mode. If set tofalse
, the mapper will ignore unknown XML/class properties. By default this flag is set totrue
.- Parameters:
strict
- strict mapping flag- Returns:
- object mapper object
-
setFormXPath
public ObjectMapper setFormXPath(java.lang.String xpath)
Set the Form XPath parameter. Any relative XPath specified will be prepended to create an absolute path.
For documents with a
<AvokaSmartForm>
root node XPath expansion examples are provided below:FormXPath Expanded XPath Applicant /AvokaSmartForm/Applicant /Applicant /AvokaSmartForm/Applicant AvokaSmartForm/Applicant /AvokaSmartForm/Applicant /AvokaSmartForm/Applicant /AvokaSmartForm/Applicant For documents with a
<Root>
root node XPath expansion examples are provided below:FormXPath Expanded XPath Applicant /Root/AvokaSmartForm/Applicant /Applicant /Root/AvokaSmartForm/Applicant AvokaSmartForm/Applicant /Root/AvokaSmartForm/Applicant /AvokaSmartForm/Applicant /Root/AvokaSmartForm/Applicant Please note you cannot specify a // search XPath as this becomes ambiguous when setting object values back into the document.
- Parameters:
xpath
- xpath parameter- Returns:
- object mapper object
-
setXPath
public ObjectMapper setXPath(java.lang.String xpath)
Set the explicit XPath parameter.
Please note you cannot specify a // search XPath as this becomes ambiguous when setting object values back into the document.
- Parameters:
xpath
- xpath parameter- Returns:
- object mapper object
-
create
public <T> T create(java.lang.Class<T> type)
Create object of the generic T type.- Type Parameters:
T
- object type that will be created- Parameters:
type
- object class type to create- Returns:
- object of the generic T type
-
update
public void update(org.w3c.dom.Document document)
Update object of the generic T type.- Parameters:
document
- XML document object
-
-