AgileApps Support Wiki Pre Release

Difference between revisions of "Document Template Classes"

From AgileApps Support Wiki
imported>Aeric
imported>Aeric
 
(49 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{TBD|In progress...}}
===About Document Template Classes===
Using a method defined in a [[Class]], you can manipulate the data that a Document Template processes.  


===About Print Template Classes===
==== How it Works ====
You can use a method in a Print Template Class to manipulate the data that a Print Template has available for processing. Here's how it works:
   
   
:* When a [[Print Template]] is processed, it gets its data from the [{{DOCHOST}}/javadocs/com/platform/api/TemplateContext.html TemplateContext]
:* When a [[Document Template]] is processed, it gets its data from the [{{DOCHOST}}/javadocs/com/platform/api/TemplateContext.html TemplateContext]


:* That object contains a HashMap for each kind of record that the Print Template can process, indexed by a string:
:* The TemplateContext contains a HashMap for a record sent to the Document Template. The HashMap contains name/value pairs for the fields in that record. It is retrieved from the context using the Object name (a string).
::* "''objectName''" - Contains the data for the record the Print Template was invoked on
:* To a Document Template then, a data object is simply a HashMap that is present in the TemplateContext.
::* "<tt>createdUsr</tt>" - Contains [[USER]] object data for the person who created the record.
::* "<tt>modifiedUsr</tt>" - Contains [[USER]] object data for the person who most recently modified the record.
{{TBD|Are the names correct? Are there any other maps?}}


:* To a Print Template, then, a data object is simply a HashMap that is present in the TemplateContext.
:* That object is passed to a method you define. By manipulating the HashMaps it contains, you change the data that the Document Template processes. You can even add new "objects", by adding additional HashMaps, and new "related objects", by adding ArrayLists of HashMaps.


:* That object is passed to a method in your Print Template class. By manipulating the HashMaps it contains, you change the data that the Print Template will be processing.
:* HashMaps and ArrayLists can be nested as deeply as needed.


In a Print Template, a data reference has the form <tt>$''objectName''.''fieldname''</tt>. To access, create, or modify data in your code, you will do one or more of the following operations:
==== Accessing Values ====
:* Retrieve a data object from the TemplateContext: <tt>TemplateContext.get("''objectName''");</tt>
:* Add or update a data object: <tt>TemplateContext.put("''objectName''", HashMap);</tt>
:* Get a field from data object: <tt>HashMap.get("''fieldName''");</tt>
:* Add or update a field in a data object: <tt>HashMap.put("''fieldName''",''value'');</tt><br>where <tt>''value''</tt> is typically a string or a nested HashMap.


{{TBD|Nesting works, yes?}}
:* When you add a simple value to the context, the corresponding template variable is <tt>${keyname}</tt>. So if <tt>"myParam"</tt> is the key, then <tt>$myParam</tt> inserts the corresponding value into the template.


===Configuring a Print Template to use a Specified Class and Method===
:* If you add a HashMap, <tt>$myParam.{hashMapKey}</tt> accesses the value for some key defined in the map. Ex: <tt>$myParam.quantity</tt>
:--select the class, and the method to use


Methods that take following arguments are listed:
:* If you add an ArrayList, you can process the list in a loop like this:
:* [{{DOCHOST}}/javadocs/com/platform/api/TemplateContext.html com.platform.api.TemplateContext] - The container that the print template gets its data from.
::<syntaxhighlight lang="java" enclose="div">
:* String (objectName) - The name of the object the print template was invoked on.  
for ($loopVariable : $myParam) {
:* String (recordID) - The ID of the record on which it was invoked.
  // work with $loopVariable here
}
</syntaxhighlight>
 
:* If the ArrayList is a list of HashMaps you process the values like this:
::<syntaxhighlight lang="java" enclose="div">
for ($loopVariable : $myParam) {
  // work with $loopVariable.{hashMapKey}. Ex: $loopVariable.quantity
}
</syntaxhighlight>
 
===Coding a Method in a Document Template Class===
In a Document Template, a data reference has the form <tt>$''objectName''.''fieldname''</tt>. To access, create, or modify data in your code, you will do one or more of the following operations:
:*;Retrieve an object's HashMap from the TemplateContext: <tt>TemplateContext.get("''objectName''");</tt>


{{TBD|TemplateContext is in new javadocs, yes? objectName is passed in, yes? Does return value have to be void?}}
:*;Add or update a data HashMap: <tt>TemplateContext.put("''objectName''", HashMap);</tt>
 
:*;Get a field from a data HashMap: <tt>HashMap.get("''fieldName''");</tt>
:*;Add or update a field in a data HashMap: <tt>HashMap.put("''fieldName''",''value'');</tt><br>where <tt>''value''</tt> is typically a string or a nested HashMap.
 
:*;Retrieve an ArrayList of HashMaps (one for each related-object record): <tt>TemplateContext.get("''RelatedObjectName''");</tt>
 
===Configuring a Document Template to use a Specified Class and Method===
To designate the class and method to use, when creating or editing a [[Document Template]]:
# Under '''Custom Data Source''', click '''Enabled'''.
# In '''Select a Class''', choose the class that has the method you want.
# In '''Select Method''' choose the method that does the processing you want.
 
The methods available to choose are public methods that have the following signature:
:<syntaxhighlight lang="java" enclose="div">
public {void} doSomething(TemplateContext context, String objName, String recordId) {
}
</syntaxhighlight>
:where:
::; [{{DOCHOST}}/javadocs/com/platform/api/TemplateContext.html <tt>com.platform.api.TemplateContext</tt>]: Is the container that the Document Template gets its data from.
::; <tt>String (objName)</tt>: Has the name of the object the Document Template was invoked on.
::; <tt>String (recordID)</tt>: Has the ID of the record on which it was invoked.
 
;Considerations:
:* Such methods generally return <tt>void</tt>, but they don't have to. Any method that takes the appropriate arguments is available, regardless of its return value.
:* A class can contain multiple processing methods, so you can do all template-related work in a single class.
:* Only one method is run, however. (You select which one.)


===Accessing Lookup Target Records===
===Accessing Lookup Target Records===
{{TBD|Is nested data stored like this?}}
Data from lookup-target records is stored as a nested map. For example, to get data for the template variable <tt>$Order.customer.name</tt>:
Data from lookup-target records is stored as a nested map. For example, to get data for the template variable <tt>$Order.customer.name</tt>:
# <tt>HashMap orderMap = TemplateContext.get("Order")</tt><br> gets the Order HashMap from the context.  
 
# <tt>HashMap customerMap = orderMap.get("customer")</tt><br> gets the lookup-target record for the customer field.
:1. '''<tt>HashMap orderMap = TemplateContext.get("Order")</tt>'''
# <tt>String name = customerMap.get("name")</tt><br> gets the customer's name.
::  Gets the Order HashMap from the context.  
 
:2. '''<tt>HashMap customerMap = orderMap.get("customer")</tt>'''
::  Gets the lookup-target record for the customer field.
 
:3. '''<tt>String name = customerMap.get("name")</tt>'''
::  Gets the customer's name.
 
===Accessing Data in Related Records===
A Document Template is always invoked on a specific record. Related-object records that look up to that record are contained in an ArrayList of HashMaps, indexed by object name. The code for obtaining and processing that kind of list looks like this:
 
:<syntaxhighlight lang="java" enclose="div">
public void chgData(TemplateContext context, String obj, String record)
{
    ArrayList<HashMap<String,Object>> listOfRecords =
        (ArrayList)context.get("SomeObject");
    if (listOfRecords == null) { listOfRecords = new ArrayList(); }
    for (HashMap<String,Object> currRecord : listOfRecords )
    {
// Process the records in this for-each loop
    }
}
</syntaxhighlight>
 
To create an entirely new breed of related "records", create an ArrayList of the appropriate type and add it to the TemplateContext.


===Examples===
===Examples===


====Changing Field Data====
====Changing Field Data====
This example substitutes the name of the state for its abbreviation, when processing a Customer record:
:<syntaxhighlight lang="java" enclose="div">
:<syntaxhighlight lang="java" enclose="div">
public void chgData(TemplateContext context, String obj, String record)
{
    HashMap customerMap = (HashMap)context.get("Customer");
    String state = customerMap.get("state").toString();
    if ( "CA".equals(state) ) {
        customerMap.put("state","California");
    }
}
</syntaxhighlight>
</syntaxhighlight>


====Example: Adding a New Field====
====Example: Adding a New Field====
This example adds a new "Good Customer" field to the Customer record.
:<syntaxhighlight lang="java" enclose="div">
:<syntaxhighlight lang="java" enclose="div">
public void addData(TemplateContext context, String obj, String record)
{
    HashMap customerMap = (HashMap)context.get("Customer");
    customerMap.put("rating", "Good Customer"); }
}
</syntaxhighlight>
</syntaxhighlight>
After that method has run, the Document Template can use the variable <tt>$Customer.rating</tt>, just as though that field was defined in the platform object.


====Example: Adding a New Object====
====Example: Adding a New Object====
This code creates a new ProductSupplier "object" (as far as the Print Template is concerned), and adds it to the TenantContext (<tt>context</tt>).
This code creates a new ProductSupplier "object" (as far as the Document Template is concerned), and adds it to the TenantContext (<tt>context</tt>).
:<syntaxhighlight lang="java" enclose="div">
:<syntaxhighlight lang="java" enclose="div">
public void procesData(TemplateContext context, String object,String record)
public void addObj(TemplateContext context, String obj, String record)
{
{
     HashMap<String, Object> productSupplierMap = new HashMap<String, Object>();
     HashMap<String, Object> productSupplierMap = new HashMap<String, Object>();
     map.put("supplierName", "Stuff R' Us");
     productSupplierMap.put("supplierName", "Stuff R' Us");
     map.put("phone", "408-555-0987");
     productSupplierMap.put("phone", "408-555-0987");
     context.put("ProductSupplier", productSupplierMap);
     context.put("ProductSupplier", productSupplierMap);
}
}
</syntaxhighlight>
</syntaxhighlight>


After that method has run, the Print Template can use the variable <tt>$ProductSupplier.phone</tt>, just as though the data had originated in the platform.
After that method has run, the Document Template can use the variable <tt>$ProductSupplier.phone</tt>, just as though the data had originated in the platform.
 
====Example: Localizing a Comparison Value====
Numeric data in the record HashMap is in the format defined by the user's locale (the [[User Format]]. To compare against a value specified in the template, either the record value must be converted to [[Database Format]], or the comparison value must be converted to [[User Format]], using the [[Java Localization Functions]].
 
Here, the <tt>order_amount</tt> is retrieved from the Order record. That amount could have a format like "4&nbsp;500,00&nbsp;&euro;" in the user's locale. This method converts the amount to the Database Format (4500.00) and stores it in the record as <tt>db_order_val</tt>:
:<syntaxhighlight lang="java" enclose="div">
import com.platform.api.*;
 
public class TemplateConversions
{
 
  public void convertAmount(TemplateContext context, String obj, String record)
  {
    HashMap orderMap = (HashMap)context.get("Order");
    String order_amount = orderMap.get("order_amount");
    String db_order_val = Functions.parseCurrency(order_amount);
    customerMap.put("db_order_val", db_order_val); }
  }
 
}</syntaxhighlight>
 
After that method has run, the Document Template can compare values that are in the same format. For example, a "big order" might be one in which the amount is greater than <tt>1000.00</tt>. So <tt>$db_order_val</tt> can be compared against that amount.

Latest revision as of 22:38, 31 October 2014

About Document Template Classes

Using a method defined in a Class, you can manipulate the data that a Document Template processes.

How it Works

  • The TemplateContext contains a HashMap for a record sent to the Document Template. The HashMap contains name/value pairs for the fields in that record. It is retrieved from the context using the Object name (a string).
  • To a Document Template then, a data object is simply a HashMap that is present in the TemplateContext.
  • That object is passed to a method you define. By manipulating the HashMaps it contains, you change the data that the Document Template processes. You can even add new "objects", by adding additional HashMaps, and new "related objects", by adding ArrayLists of HashMaps.
  • HashMaps and ArrayLists can be nested as deeply as needed.

Accessing Values

  • When you add a simple value to the context, the corresponding template variable is ${keyname}. So if "myParam" is the key, then $myParam inserts the corresponding value into the template.
  • If you add a HashMap, $myParam.{hashMapKey} accesses the value for some key defined in the map. Ex: $myParam.quantity
  • If you add an ArrayList, you can process the list in a loop like this:
<syntaxhighlight lang="java" enclose="div">

for ($loopVariable : $myParam) {

 // work with $loopVariable here

} </syntaxhighlight>

  • If the ArrayList is a list of HashMaps you process the values like this:
<syntaxhighlight lang="java" enclose="div">

for ($loopVariable : $myParam) {

 // work with $loopVariable.{hashMapKey}. Ex: $loopVariable.quantity

} </syntaxhighlight>

Coding a Method in a Document Template Class

In a Document Template, a data reference has the form $objectName.fieldname. To access, create, or modify data in your code, you will do one or more of the following operations:

  • Retrieve an object's HashMap from the TemplateContext
    TemplateContext.get("objectName");
  • Add or update a data HashMap
    TemplateContext.put("objectName", HashMap);
  • Get a field from a data HashMap
    HashMap.get("fieldName");
    Add or update a field in a data HashMap
    HashMap.put("fieldName",value);
    where value is typically a string or a nested HashMap.
  • Retrieve an ArrayList of HashMaps (one for each related-object record)
    TemplateContext.get("RelatedObjectName");

Configuring a Document Template to use a Specified Class and Method

To designate the class and method to use, when creating or editing a Document Template:

  1. Under Custom Data Source, click Enabled.
  2. In Select a Class, choose the class that has the method you want.
  3. In Select Method choose the method that does the processing you want.

The methods available to choose are public methods that have the following signature:

<syntaxhighlight lang="java" enclose="div">

public {void} doSomething(TemplateContext context, String objName, String recordId) { } </syntaxhighlight>

where:
com.platform.api.TemplateContext
Is the container that the Document Template gets its data from.
String (objName)
Has the name of the object the Document Template was invoked on.
String (recordID)
Has the ID of the record on which it was invoked.
Considerations
  • Such methods generally return void, but they don't have to. Any method that takes the appropriate arguments is available, regardless of its return value.
  • A class can contain multiple processing methods, so you can do all template-related work in a single class.
  • Only one method is run, however. (You select which one.)

Accessing Lookup Target Records

Data from lookup-target records is stored as a nested map. For example, to get data for the template variable $Order.customer.name:

1. HashMap orderMap = TemplateContext.get("Order")
Gets the Order HashMap from the context.
2. HashMap customerMap = orderMap.get("customer")
Gets the lookup-target record for the customer field.
3. String name = customerMap.get("name")
Gets the customer's name.

Accessing Data in Related Records

A Document Template is always invoked on a specific record. Related-object records that look up to that record are contained in an ArrayList of HashMaps, indexed by object name. The code for obtaining and processing that kind of list looks like this:

<syntaxhighlight lang="java" enclose="div">

public void chgData(TemplateContext context, String obj, String record) {

   ArrayList<HashMap<String,Object>> listOfRecords =
       (ArrayList)context.get("SomeObject");
   if (listOfRecords == null) { listOfRecords = new ArrayList(); }
   for (HashMap<String,Object> currRecord : listOfRecords )
   {

// Process the records in this for-each loop

   }		

} </syntaxhighlight>

To create an entirely new breed of related "records", create an ArrayList of the appropriate type and add it to the TemplateContext.

Examples

Changing Field Data

This example substitutes the name of the state for its abbreviation, when processing a Customer record:

<syntaxhighlight lang="java" enclose="div">

public void chgData(TemplateContext context, String obj, String record) {

   HashMap customerMap = (HashMap)context.get("Customer");
   String state = customerMap.get("state").toString();
   if ( "CA".equals(state) ) { 
       customerMap.put("state","California"); 
   }

} </syntaxhighlight>

Example: Adding a New Field

This example adds a new "Good Customer" field to the Customer record.

<syntaxhighlight lang="java" enclose="div">

public void addData(TemplateContext context, String obj, String record) {

   HashMap customerMap = (HashMap)context.get("Customer");
   customerMap.put("rating", "Good Customer"); }

} </syntaxhighlight>

After that method has run, the Document Template can use the variable $Customer.rating, just as though that field was defined in the platform object.

Example: Adding a New Object

This code creates a new ProductSupplier "object" (as far as the Document Template is concerned), and adds it to the TenantContext (context).

<syntaxhighlight lang="java" enclose="div">

public void addObj(TemplateContext context, String obj, String record) {

   HashMap<String, Object> productSupplierMap = new HashMap<String, Object>();
   productSupplierMap.put("supplierName", "Stuff R' Us");
   productSupplierMap.put("phone", "408-555-0987");
   context.put("ProductSupplier", productSupplierMap);

} </syntaxhighlight>

After that method has run, the Document Template can use the variable $ProductSupplier.phone, just as though the data had originated in the platform.

Example: Localizing a Comparison Value

Numeric data in the record HashMap is in the format defined by the user's locale (the User Format. To compare against a value specified in the template, either the record value must be converted to Database Format, or the comparison value must be converted to User Format, using the Java Localization Functions.

Here, the order_amount is retrieved from the Order record. That amount could have a format like "4 500,00 €" in the user's locale. This method converts the amount to the Database Format (4500.00) and stores it in the record as db_order_val:

<syntaxhighlight lang="java" enclose="div">

import com.platform.api.*;

public class TemplateConversions {

 public void convertAmount(TemplateContext context, String obj, String record)
 {
   HashMap orderMap = (HashMap)context.get("Order");
   String order_amount = orderMap.get("order_amount");
   String db_order_val = Functions.parseCurrency(order_amount);
   customerMap.put("db_order_val", db_order_val); }
 }

}</syntaxhighlight>

After that method has run, the Document Template can compare values that are in the same format. For example, a "big order" might be one in which the amount is greater than 1000.00. So $db_order_val can be compared against that amount.