 |
|
|
 |
| April 2001 |
 |
| DeveloperNet University Course |
 |
 |
Java Programming Projects
 Module Objective: After studying the concepts in this section, you should be able to:
1. Describe the PBXSimulator APIs available to DirXML drivers.
2. Describe the DOM JavaDoc needed to use Java DOM APIs
3. Describe how to build very basic XDS parsing code using Java DOM APIs.
Note: If you haven't done so already, download the course folder to your development machine at this time.

Important
You must understand how to interpret NDS.DTD for all of the projects in this section. If you feel weak on that topic, now would be a good time to review. Analyzing NDS.DTD to Construct XDS Trees
- Review the PBXSimulator application APIs.
- One of the major pre-requisites to writing a DirXML driver is knowledge of the external application. You must thoroughly understand your application's interface in order to write code for a DirXML driver's Publication and Subscription shims.
- To simplify this as much as possible for the labs, the lab drivers use a java interface to interact with PBXSimulator. The following code describes this interface to PBXSimulator.
Carefully read the comments in the java interface below to help you understand how your Java code will interact with PBXSimulator.
package pbx; import java.util.*; /* THIS INTERFACE DEFINES THE PBXSIMULATOR APPLICATION APIS THAT ARE AVAILABLE TO A DIRXML DRIVER. */ public abstract interface PBXSimulatorInterface { // THESE ARE THE TWO NDS CLASSES USED BY PBXSIMULATOR public static final String PBX_ACOUNT_CLASS = "User"; public static final String PBX_LOCALE_CLASS = "Organizational Unit"; // EMPLIDS ARE THE UNIQUE IDS FOR ACCOUNTS FROM PBXSIMULATOR // WHICH ARE USED TO CREATE ASSOCIATIONS TO OBJECTS IN NDS public final static String API_UNIQUE_ID = "Employee ID"; // THE LAB PUBLISHER USES getPBXEvents() TO OBTAIN A VECTOR OF VECTORS. // EACH BOTTOM LEVEL VECTOR ELEMENT CONTAINS STRING // ELEMENTS DESCRIBING A PARTICULAR EVENT. // e.g. THE ELEMENTS BELOW COMMAND THE PUBLISHER TO ADD USER // LORENZO FISHER TO NDS // "evtType^add employee" // "emplid^0199" // "firstName^Lorenzo" // "lastName^fisher" // "title^Senior Software Engineer" // "phone^861-6516" // "department^Engineering" // "location^Provo" // "CN^larry" public Vector getPBXEvents( ); // THE LAB PUBLISHER USES getEventDataAtIndex() TO OBTAIN THE BOTTOM LEVEL // VECTORS FROM THE VECTOR OF VECTORS OBTAINED USING getPBXEvents(). // SEE THE EXPLANATION FOR getPBXEvents() ABOVE. WHERE THE eventVector // PARAMETER IS THE VECTOR OF VECTORS. EACH BOTTOM LEVEL VECTOR // DESCRIBES AN EVENT. THE index PARAMETER SPECIFIES WHICH EVENT TO // OBTAIN. public Vector getEventDataAtIndex( Vector eventVector, int index ); // THE LAB SUBSCRIBER CALLS processNDSEvt() AFTER IT HAS CONVERTED AN // NDS EVENT FROM XDS INTO THE STRING FORMAT USED BY PBXSIMULATOR. // e.g. THE STRING BELOW COMMANDS PBXSIMULATOR TO ADD USER LORENZO FISHER // evtType^add employee,emplid^0199,firstName^Lorenzo,lastName^fisher // NOTE: EMPLID VALUES USED TO CREATE AN ASSOCIATION BETWEEN NEW // ACCOUNTS IN PBXSIMULATOR AND OBJECTS IN NDS ARE OBTAINED // FROM PBXSIMULATOR USING getNewPBXAssocKey() DESCRIBED LATER. public void processNDSEvt(String newEvtsStr ); // THE LAB SUBSCRIBER CALLS getNewPBXAssocKey() TO OBTAIN A UNIQUE ID FOR // AN ACCOUNT TO BE CREATED IN PBXSIMULATOR. THE EMPLID IN THE STRING // BELOW WOULD BE OBTAINED USING getNewPBXAssocKey(). THE STRING WOULD // THEN BE SENT TO PBX SIMULATOR USING processNDSEvt() [DESCRIBED ABOVE]. // e.g. THE STRING BELOW COMMANDS PBXSIMULATOR TO ADD USER LORENZO FISHER // evtType^add employee,emplid^0199,firstName^Lorenzo,lastName^fisher1 public String getNewPBXAssocKey( ); // THE LAB SUBSCRIBER CALLS isValidPBXLocale() TO VERIFY THAT PBXSIMULATOR // ALREADY HAS THE SPECIFIED LOCATION (CITY) AND DEPARTMENT IN ITS LOCALES // ["loc.txt" FILE]. public boolean isValidPBXLocale(String chkLocation, String chkDepartment ); // THE LAB SUBSCRIBER CALLS addLocale() TO ADD THE SPECIFIED LOCATION (CITY) // AND/OR DEPARTMENT TO PBXSIMULATOR'S LOCALES ["loc.txt" FILE]. public boolean addLocale( String srcLoc,String srcDept ); // THE LAB SUBSCRIBER CALLS deleteLocale() TO DELETE THE SPECIFIED LOCATION // (CITY) AND/OR DEPARTMENT FROM PBXSIMULATOR'S LOCALES ["loc.txt" FILE]. public boolean deleteLocale( String srcLoc,String srcDept ); // THE LAB QUERYHANDLER CALLS getSelectedObjects() TO OBTAIN REFERENCES TO // ALL PBX ACCOUNTS LOCATED WITHIN THE SPECIFIED LOCATION AND/OR DEPT // if( targetLoc != null && targetDept != null ) // /* returns all accounts in specified locale, association is ignored */ // else if((targetLoc== null&& targetDept == null) && association != null ) // /* returns single account with specified association [emplid value]*/ // else if(targetLoc == null && targetDept == null && association == null ) // /* returns all accounts */ public Vector getSelectedObjects( String loc, String dept, String assoc ); // THE LAB QUERYHANDLER CALLS getSelectedObjVals() TO OBTAIN THE VALUES // LISTED IN itemNames FROM THE PBX ACCOUNTS LISTED IN objectIDs // THE RETURNED VECTOR CONTAINS A VECTOR FOR EACH OBJECT IN THE objectIDs // VECTOR. EACH OF THE OBJECT VECTORS WILL CONTAIN STRING VALUES FOR EACH // ITEM NAMED IN THE itemNames VECTOR. THE ITEMS IN EACH OBJECT VECTOR // WILL ALSO BE ALIGNED WITH THE ITEMS IN THE itemNames VECTOR. public Vector getSelectedObjVals(Vector objectIDs , Vector itemNames ); // THE LAB DRIVER CALLS killPBX() TO RELEASE ALL PBXSIMULATOR RESOURCES // [WINDOWS, ETC.] BEFORE THE DRIVER EXITS public void killPBX() }
- Review DOM APIs.
- The DOM (Document Object Model) establishes a standard way of looking at the components in XML. DOM APIs are industry standards established by the World Wide Web Consortium (W3C) to manipulate DOM document components. DirXML implements these APIs for your use in writing drivers.
- Lab 1's Publisher shim already contains the DOM API programming needed to process object add and delete events going from PBXSimulator to NDS.
- During the fourth lab, you'll be asked to do the DOM API coding needed to process object modify events going from PBXSimulator to NDS.
- Lab 1's Subscriber shim already contains the DOM API programming needed to process object add and delete events going from NDS to PBXSimulator.
- During the fifth lab, you'll be asked to do the DOM API coding needed to process object modify events going from NDS to PBXSimulator.
-
To review the JavaDoc for the DOM APIs used in this course, double-click "c:\DirXMLCrsFldr\Docs\index.html".
-
Once the browser has loaded the "index.html" file, click "org.W3C.dom" in "Packages". Then click "org.W3C.dom" in the resulting "Interfaces" listing below. Finally click the "Tree" view to see the inheritance relationship of the DOM interfaces as shown in the diagram below.
-
Read about all of the DOM interfaces in the "org.w3c.dom" interface and their methods in the JavaDoc, paying special attention to the following:
Class
|
Method
|
Document
|
getElementsByTagName()
|
NodeList
|
item()
|
Node
|
getFirstChild()
getLastChild()
getNodeValue()
getNodeName()
getNodeType()
|
-
Refer to the NDS.DTD excerpt, the XDS document, and the node tree diagram for the document below as you read the following DOM Programming Explanation.
NDS.DTD Excerpt
<!ELEMENT driver-config (driver-options?, subscriber-options?, publisher-options?) > <!ATTLIST driver-config name CDATA #IMPLIED>
<!ELEMENT config-object (query) > <!ATTLIST config-object display-name CDATA #IMPLIED>
<!ELEMENT driver-options (ANY | config-object)* > <!ELEMENT subscriber-options (ANY | config-object)* > <!ELEMENT publisher-options (ANY | config-object)* >
XDS Document Sample
<?xml version="1.0" encoding="ISO-8859-1" ?> 0 <driver-config name="PBX Simulator Driver Shim"> 1 <driver-options> 2 <pbxDBFilePath display-name="PBX Database File Path"> 3 c:\SolutionLabDriver\pbx\ </pbxDBFilePath> 4 <pbxNDSPath display-name="NDS Context for PBX Objects"> 5 \TESTTREE\Novell\ </pbxNDSPath> </driver-options> <subscriber-options> </subscriber-options> <publisher-options> </publisher-options> </driver-config>
Sample XDS Document's Node Tree
DOM Programming Explanation
An XmlDocument object is simply a DirXML wrapper for an XML document. A DOM Document is simply an object conforming to the W3C's model of what an XML document should look like.
DirXML communicates with XmlDocuments (XML/XDS documents) which can be textually represented by documents like the sample shown above. However your shim code is going to manipulate documents using DOM APIs. So, the first thing you need to do is to instantiate a DOM Document from the XmlDocument.
This can be done simply by using the XmlDocument's getDocument( ) API (XmlDocument is a Novell defined class).
In the example below, assume that "xmlDoc" is an instance of the XDS document shown above, perhaps inputted to your Driver shim's init( ) method.
String pbxDBFilePath = null; Document doc = xmlDoc.getDocument( );
The value returned from getDocument( ) would be a DOM Document containing the same information as that in the XmlDocument (see JavaDoc for more information on the Document class).
Now you have a DOM document. After referring to NDS.DTD to figure out the composition of the event document that you are looking for (what can be a child of what and how many of them there are), you can write DOM code to programmatically obtain items of interest from documents of that event type.
For example, you might want to obtain a string for the text child of the <pbxDBFilePath> element in the document above. The first step is to identify a unique, known element containing your target information. This could be the parent of the target value, or its parent, etc.
It is important that the initial element that you choose to access in combination with the children you choose to access leading up to the target information, establish a unique context path to the information.
You can see from the NDS.DTD excerpt above that there is zero or one <driver-options> child elements allowed in a <driver-config> element. So, we know that <driver-options> is a unique parent element leading to our target.
However, its children can be any number of elements by any name (defined in the DTD by "ANY"). This is done for the <driver-config> element because driver parameter names are invented as part of the configuration process and are editable by the administrator in the Driver object's Parameters panel. So, they are certainly application defined and often installation defined.
For example, the two values in the above sample were invented to make the PBXSimulator driver more configurable. You see, in the first two labs, the location of the "pbx" directory accessed by the driver shim is hard-coded into the shim itself, requiring a recompilation of this executable if the directory is ever moved.
By adding the new driver parameters shown in the sample and then supporting them with corresponding parsing code in the driver shim, the administrator is allowed to move the location of the PBXSimulator driver file and then simply use ConsoleOne to modify the Driver object's path parameter value as appropriate.
So, even though NDS.DTD has no knowledge of the <pbxDBFilePath> element, we'll assume since we invented it, that that there is only one of them. Since <pbxDBFilePath> is the closest, unique parent element to our target information, we will obtain it directly using the Document class's method, NodeList getElementsByTagName( String elmntName );
Remember, we already have a Document named "doc", so the call would look like this:
String pbxDBFilePath = null; Document doc = xmlDoc.getDocument( ); NodeList nodes = doc.getElementsByTagName("pbxDBFilePath");
Note: Refer to the DOM JavaDoc for more information on the Node, NodeList, Element, and Document classes and their methods.
The getElementsByTagName( ) method will always return a NodeList (with length equal to zero if there are no elements with the specified name). So, since we know that <pbxDBFilePath> will only have one value (we know this because we invented it), we can obtain the element like this:
String pbxDBFilePath = null; Document doc = xmlDoc.getDocument( ); NodeList nodes = doc.getElementsByTagName("pbxDBFilePath"); if( nodes.getLength() > 0) { Element parentNode = (Element)nodes.item(0); }
After examination of the XDS sample above, it would be tempting to call the Element class's getNodeValue( ) method on parentNode to obtain the target information "c:\SolutionLabDriver\pbx\". However, this would be premature. You see, even though the XML text in the example above looks as if the text value is a part of the <pbxDBFilePath> element, in actually DOM sees it as a separate child text node. So, we need to obtain the child node of parentNode and then get its value.
To do this, we can use the Node class's getFirstChild( ) method.
String pbxDBFilePath = null; Document doc = xmlDoc.getDocument( ); NodeList nodes = doc.getElementsByTagName("pbxDBFilePath"); if( nodes.getLength() > 0) { Element parentNode = (Element)nodes.item(0); Node textNode = parentNode.getFirstChild(); if (textNode != null) { pbxDBFilePath = textNode.getNodeValue(); pbxDBFilePath = pbxDBFilePath.trim(); } }
Note: trim( ) is a java.lang.String method that removes white-space from before the first non-white-space character and after the last one.
At this point, you should have a pretty good idea of how to learn about PBXSimulator APIs and DOM APIs.
You may now proceed to the labs.
|