Validating Update Requests

Suppose now our system receives a message containing an address change request (tc=181 in ACORD parlance). Before even processing it, however, we want to make sure the message is semantically valid (not just valid in terms of the ACORD standards); in particular we want to ensure that:

  • the person exists
  • the old address exists
  • the new ZIP code is valid
  • the new ZIP code corresponds to the new state

The XQuery implementing such validation is shown here (click this link to open the XQuery document):

declare namespace tx="http://ACORD.org/Standards/Life/2";
  
import module namespace example = "http://www.datadirect.com/xquery/examples" at "acord_verbs.xquery";
 
(: Example of business validation on an "Address Change" request :)
let $request := doc("181-1.xml")
return example:validate-181($request/tx:TXLife/tx:TXLifeRequest)

As you can see in acord_verbs.xquery, example:validate-181() fetches data from two relational tables (ACORD_PERSON and ACORD_ADDRESS), performs the various checks, and returns either an empty result (no errors; success), or a message describing the error condition (failure). The first part of the function is particularly interesting, as it is responsible for implementing the actual business validation rules:

declare function example:validate-181($request as element(tx:TXLifeRequest)) as element(tx:TXLifeResponse)? {
	let $party := $request/tx:OLifE/tx:Party[@id eq $request/@PrimaryObjectID]
	let $key := xs:string($party/tx:PartyKey)
	let $person := collection("ACORD_PERSON")/ACORD_PERSON[PartyKey eq $key]
	let $oldAddress := $party/tx:Address[@DataRep eq "Removed"]
	let $newAddress := $party/tx:Address[@DataRep eq "Full"]
	let $row := collection("ACORD_ADDRESS")/ACORD_ADDRESS
		[OwnerKey eq $key]
		[AddressTypeCode eq xs:integer($oldAddress/tx:AddressTypeCode/@tc)]
		[Line1 eq $oldAddress/tx:Line1]
		[City eq $oldAddress/tx:City]
		(: AddressState is nullable :)
		[AddressState eq $oldAddress/tx:AddressState 
		or 
		fn:empty(AddressState) and fn:empty($oldAddress/tx:AddressState)]
		[Zip eq $oldAddress/tx:Zip]
		[AddressCountry eq $oldAddress/tx:AddressCountry]
	let $rowValid := fn:count($row) eq 1
	let $zipState := 
		if ( $newAddress/tx:AddressCountry eq "USA" )
		then 
			example:getZipInfo($newAddress/tx:Zip)
		else
			() 
...

Validation of the ZIP code, when "AddressCountry" is "USA" is delegated to the example:getZipInfo() function, which in turns delegates validation to a third party public Web Service, published by http://www.webservicemart.com (http://www.webservicemart.com/uszip.asmx):

declare function example:getZipInfo($zipCode as xs:string) as element()? {
	let $response :=
		ddtek:wscall(
	<ddtek:location address="http://www.webservicemart.com/uszip.asmx" 
							soapaction="http://webservicemart.com/ws/ValidateZip"/>,
								 
			<ws:ValidateZip>
				<ws:ZipCode>{$zipCode}</ws:ZipCode>
			</ws:ValidateZip> 
		)/ws:ValidateZipResponse/ws:ValidateZipResult
return 
	(: because the webservice returns the result as text (not xml) wrapped 
		in a ValidateZipResult node we have to parse the content :)
		ddtek:parse($response/text())/*
};

Thanks to the ddtek:wscall() function, invoking external Web Service from a DataDirect XQuery™ is extremely simple, as you can see.

What's Next

Now that you see how to use DataDirect XQuery™ to validate data, go to Updating a Relational Database to learn how to update relational data with DataDirect XQuery™.

Prev: "Search and Inquiry Using Multiple Joins"

Next: "Updating a Relational Database"


Copyright © 1993 - 2008. Progress Software Corporation. All rights reserved. | N. America: 800 876 3101 | World: +44 (0) 1753 218 930