Avoka Blog: Adobe LiveCycle

February 9, 2009

Using the Avoka XQuery Service Component

Filed under: Components, Designing Processes — Jason Hendry @ 8:46 am

Livecycle has some useful Service components for manipulating files, database rows and XML documents. And while XSLT is a powerful and useful language, it can sometimes be a little unwieldy to express simple logical problems.

I recently had to perform some simple logical programming on the server side to select one of three text fields on a form. The text fields were comments from users and the last user to touch the form before exiting the flow had their comments inserted into an email back to the form originator. There are a multitude of different ways of handling this problem on the form instead of on the server, however, this problem came to me as a system maintainer and there were constraints I had to observe.

Avoka’s XQuery component makes it possible to construct strings and XML fragments using the XQuery language. XQuery, as you may know, has a syntactic structure called FLWOR or

For
Let
Where
Order
Return

This is typified by the example given on W3Schools using the Books XML data sample:

for $x in doc("books.xml")/bookstore/book
where $x/price>30
order by $x/title
return $x/title

*Note that the Let is implied in $x in doc(…)/bookstore/book

But what I needed was not an iterative solution (at least, not one that required a for loop), but a way to simply express the conditional logic to select the first non-empty XML text node.

To test the hierarchy of user’s for the last commenter, I could have used a number of Decision and Set components, but why take 3 steps when you can take 1?

Alternately, I could have implemented similar logic using the Livecycle script component and while it would have performed in a single workflow step, the script component can be unwieldy when manipulating form values. Do you really want to …

patExecContext.getProcessDataStringValue("/process_data/status");

… just to test a couple of values?

Step 1: Workflow

There are two possible types of invocation on the XQuery Service Component, Single Document and Merge Document.  The Merge Document invocation is intended to be more powerful so in this example we’ll be considering the Single Document invocation of the XQuery component.

I inserted the XQuery component (Last Commenter) into the workflow, just before the email step to notify the originator of the last user’s comments.   This is where we’ll test the form data variable for the comment fields, and then copy them into another process variable to be inserted in the email.

Inserting the XQuery service object into the workflow

Inserting the XQuery service object into the workflow

Step 2: Service Configuration Parameters

The XQuery object is fairly simple to setup, only requiring an XQuery statement and an Output location. In the example here, I’m using a variable, emailCreditComments, to capture the comment tex which I’ll re-use in the following email workflow step.

Configuring the Avoka XQuery Service Component

Configuring the Avoka XQuery Service Component

Step 3: XQuery Statement

First, I chose a location in my process variables to act as the root of my XQuery statement. This is a parameter of the statement, rather than the XQuery configuration and acts to reduce the size of the document the XQuery statement operates on.  Since I’m looking for comment fields, I set the location deep into my XFA form variable structure:

/process_data/form/object/data/xdp/datasets/data/DocumentRoot

In this example, I’m using the root of the XFA data passed into the process as a form variable.

Next, as a matter of style, I set the form comments text into re-usable variables that I can test.

let $sp := //FormData/SeniorPartner/Comments/text()

Then, I constructed a logic statement that allowed for graceful regression without forcing the flow. In most functional programming languages, this style of cascading if() statement is to be avoided since it can become a real headache for maintainers. However, the nature of service components in Livecycle means that we can consider (and re-use!) pieces of functionality independently.

let $sp := //FormData/SeniorPartner/Comments/text()
let $hod := //FormData/HeadOfDepartment/Comments/text()
let $mgr := //FormData/Manager/Comments/text()
return if (string-length($sp) = 0)
	then if(string-length($hod) = 0)
		then $mgr
	else $hod
else $sp

As you can see the statement itself is quite simple, cascading from each if() statement, testing for validity in the order of the user hierarchy (Senior Partner, Head of Department, Manager). Validity in this case is a test for string length, such that any test that fails indicates we have a non-empty comment text node.  The first test to fail gets it’s comment text returned via the else clause and inserted into the configured output location.

XQuery Service Configuration Statement
Lastly, since the result of the XQuery statement will be inserted into an email, rather than re-used as an XML data set, we tell the XQuery service component to omit the XML processing instruction. Other options include the ability to ‘pretty print’ the output and to re-use namespaces from the source process definition.

Summary

This example demonstrates a simple, if somewhat unusual use of the XQuery language implemented using the Avoka XQuery Service Component.

References

http://manly.avoka.com/confluence/display/Public/XQuery+DSC

http://www.w3schools.com/xquery/default.asp

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: