|
||||
|
|
Registered Active Accessors create new instructions that are accessible by languages like DPML. The system comes preconfigured with many active accessors which perform operations from simple copying of documents to evaluation of complex languages such as XQuery. Active URAs and InstructionsThe link between instructions and Active Accessors isn't obvious. As a developer
of Idocs and user of accessors it isn't necessary to know. However the DPML interpretter
transforms instructions into URIs. We call these URIs active URIs. They are of the form
A guide to active URI's is provided here. The best way to show what is necessary to create an active URA is to run though a simple example. ExampleAs an example we will develop an accessor to convert a document's text elements to
all uppercase or lowercase depending upon an optional operator document.
We will map the accessor to the <instr>
<type>org.myDomain.myApp.case</type> <operand>var:input</operand> <operator> <case>upper</case> </operator> <target>var:output</target> </instr> Let us assume that we have already created a basic module in which to place the accessor. A seperate guide to creating a module is provided here. We now follow some basic steps to create the new Active Accessor. Step 0 - prepare classpathAn accessor must be built against the 1060netkernel.jar and any additional modules you are using the classes or resources from. The Active Accessor in this example extends XAccessor and uses classes from the layer1 and ext_xml modules. These modules should be in your classpath for building. However they should not be in your classpath for execution or debug since the Kernel always automatically discovers and installs module resources at boot time. Step 1 - declare classSubclass
/*
* CaseAccessor.java
*
*/
package org.myDomain.myApp;
import com.ten60.netkernel.urii.*;
import org.ten60.netkernel.xml.xahelper.*;
/**
* Case Accessor changes case of all text entries an XML document
*/
public class CaseAccessor extends XAccessor
{
/** Creates a new instance of CaseAccessor */
public CaseAccessor()
{ declareArgument(OPERAND, true, false);
declareArgument(OPERATOR, false, false);
}
/**source request**/
protected IURRepresentation source(XAHelper aHelper) throws Throwable
{
}
}
Step 2 - implement methodImplement the method
/**source request**/
protected IURRepresentation source(XAHelper aHelper) throws Throwable
{ Document operand = aHelper.getOperand().getReadOnlyDocument();
Document result = (Document)XMLUtils.getInstance().safeDeepClone(operand);
boolean toUpper=true;
if (aHelper.hasOperator())
{ toUpper = aHelper.getOperator().getXDA().isTrue("/case[text()='upper']");
}
recurse(result.getDocumentElement(),toUpper);
IURMeta meta=aHelper.getDependencyMeta("text/xml", 8);
DOMXDA resultXDA=new DOMXDA(result,false);
return DOMXDAAspect.create(meta, resultXDA);
}
/*Recursively change case of text elemenets*/
private void recurse(Element e, boolean toUpper)
{ //Complete as exercise for reader
}
In this example we first retrieve the operand argument as a ReadOnly DOM. All arguments are implemented as IURRepresentations objects which are immutable since they may be referenced by many concurrent applications. Therefore to use an argument obtained from a IURRepresentation in a non-readonly fashion it must be cloned. DOM does not implement a readonly interface so we use the XMLUtils utility class to perform a safeDeepClone of the operand document. Next XAHelper is used to see if we received an operator argument. If we have we perform an XPath evaluation to see if it specified 'upper' or 'lower' case. The cloned result DOM is passed to the recurse() method. We'll leave it to you to think how you'd implement this. The XAHelper creates a DependencyMeta with dependencies on each resource we have accessed and declares things such as MIME type, in this case "text/xml", and cost. This is very useful for the dependency based cache of the NetKernel.
The processed result DOM is wrapped in a DOMXDA object. DOMXDA is DOM implementation of the XDA interface - this interface provides
very convenient XPath based operations, including iterators, on an underlying XML document.
Finally we use a That's the Active URA completed. Next it has to be registered with it's parent module in the module.xml declaration so that it can be used. Step 3 - register AccessorA detailed guide to creating a module definition is provided here. Here we will show how to export our Accessor on the public interface of a module and the internal mapping required to instantiate the class for it.
The Accessor must be registered in the internal address space of the module.
This is done by declaring a <mapping>
...
<ura> <match>active:org.myDomain.myApp.case.*</match> <class>org.myDomain.myApp.CaseAccessor</class> </ura> ... </mapping> The The If you want the accessor to be available publicly, that is not just for use internally within the module itself, the module definition must export the active URIs that will invoke our accessor. This is done with the following entry in the export section. <export>
...
<uri> <match>active:org.myDomain.myApp.case.*</match> </uri> ... </export>
That's it. Restart NetKernel to reload the modules.
Your
|
|||
|
© 2003,2004, 1060® Research Limited
1060 registered trademark, NetKernel trademark of 1060 Research Limited
|
||||