Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
1,62 MB
Nội dung
382 Chapter 10 JSP Taglib: The bonForum Custom Tags the transform tag is called, invoking the methods of its handler class.The following code in that handler, from TransformTag.java, takes care of getting the style-sheet para- meter: String param1 = (String)pageContext.getSession( ).getAttribute( “param1” ); if( param1 == null) { param1 = “”; } The TransformTag class invokes an XSLT processing method in one of several ways, depending on the tag attribute values. Every such invocation, whether for Xalan-Java 1 or Xalan-Java 2, passes the style-sheet parameter as an argument, like this: transformer.transform(inXML, inXSL, outDoc, param1) 10.9.5 How the Style Sheet works The first template in the style sheet matches the root node. It begins an HTML select element and then applies templates to all the bonForum.things nodes. A chat element is found whose itemKey value matches the param1 value passed by the JSP tag action.That is the current chat for the session.The children of that chat element are iterated looking for any guestKey elements.Whenever one is found, its value (a nodeKey string) is saved in the guestKey-value variable, and the processing jumps to a different place altogether in the bonForum XML data: Guest elements (children of the bonForum.actors node) are iterated.When a guest element nodeKey value matches the saved guestKey value, that element is a guest in the chat. Its nickname, age, and rating element contents can now be concatenated as an HTML option for the select that is being built by this style sheet.The iteration of the guestKey s in the chat continues until all the HTML option strings have been output.The closing tag for the HTML select is output as well. Why the Style Sheet Is Used As we discussed in the section “The changeChatActorRating() Method” in Chapter 8, a chat host has commands available to raise or lower the rating of any guest in the “current” chat. (That functionality will later be extended to allow any chat actor to rate any other one in its chat.) Now you know how that host gets a list of the guests in its chat so that it can pick one to promote or demote. 10.9.6 JSP Tags and XSLT in the Future One of the main goals of our Web application design is that it should be extensible and customizable using technologies designed for such purposes.The two most pow- erful ways to turn the bonForum prototype into a chat that is visually appealing and full of features are JSP custom tags and XSLT processing. 10 1089-9 CH10 6/26/01 7:35 AM Page 382 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 383 10.9 Displaying the Guests ina Chat 10.9.7 Sending Feedback to the Author We hope that you enjoy altering and improving the JSP documents and the XSL style sheets as much as we enjoyed creating the ones shown here.To send your own solu- tions, improvements, donations, and flames, or to discuss the contents of this book, feel free to email the author of this book at email@bonforum.org , or use the forums and mailing lists provided by SourceForge to reach the bonForum project Web site: http://www.bonforum.org . 10 1089-9 CH10 6/26/01 7:35 AM Page 383 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 10 1089-9 CH10 6/26/01 7:35 AM Page 384 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. XML Data Storage Class: ForestHashtable 11 I N THIS CHAPTER , YOU CAN LEARN HOW we implemented data storage for the XML data in the bonForum chat application. A descendant of the Hashtable class adds a few tricks to optimize XML element retrieval, as it simulates our design for a relational database schema. 11.1 Overview of bonForum Data Storage One of the more controversial aspects of the bonForum project has been its data stor- age implementation.Throughout this chapter, we will include some of the objections that have been raised. Perhaps the most common question is why did we not use a relational database. Certainly, that would not have been as difficult as creating the ForestHashtable class inJava, right? Questions are also raised about the way we designed our objects.These questions deserve an answer, so here are three: n We are not against using a database—in fact, we will. However, we wanted to design ours (and experiment with its design) without using a database tool. As you read this chapter, be aware that we are not trying to replace the use of a database engine—or to reinvent, one either. n Our objective was never to design the best way of storing, manipulating, and retrieving XML data using Java objects. Instead, we were using Java objects to simulate and test a table design for a relational database. 11 1089-9 CH11 6/26/01 7:36 AM Page 385 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 386 Chapter 11 XML Data Storage Class: ForestHashtable n We did it this way because we believe that putting a problem into a different context than its usual one often stimulates insights into the problem that would otherwise go unseen. Paradoxically, doing it the hard way first can help you find the best way sooner. The de.tarent.ForestHashtable class extends the java.util.Hashtable class. In this chapter, we assume that you are familiar with the Hashtable class. If you are not, or if you have questions about it, consult the API documentation for the Java SDK you are using. Briefly, a Hashtable instance keeps track of a number of objects called elements. When you add an element to a Hashtable , you associate it with another object called a key.You can later use this key to find the element again. Because our ForestHashtable class is a descendant of a Hashtable , it can serve as the object storage facility for our Web application example project. Note that the term element is used in this chapter with two different definitions: an object held by a Hashtable , anda type of XML node. Hopefully, each time the term appears, context will differentiate between the two meanings. 11.1.1 ForestHashtable Stores Simple XML A ForestHashtable caches XML documents for fast processing. Each element ina ForestHashtable is an object that can be cast to a BonNode object, and each key is an object that can be cast to a NodeKey object.The BonNode objects are mappable to the element nodes in one or more XML documents.The NodeKey objects are designed to keep track of the hierarchical tree relationship that exists between the XML nodes. How this all works is the first subject of this chapter. 11.1.2 ForestHashtable Is an Experiment Please note that ForestHashtable is still ina primitive state of development and should be considered an experiment rather than an attempt to provide a comprehen- sive XML storage object. In fact, in the version discussed in this book and used in its Web application project, a ForestHashtable stores only XML element nodes and any of their children that are either attribute nodes or text nodes. Other XML node types besides these are ignored. 11.1.3 A Preview of This Chapter By reading this far in the book, you have already learned enough theory about the ForestHashtable class used in the bonForum Web application.These are the major points that should be familiar as we proceed: n The ForestHashtable is a customized Hashtable whose elements are BonNode objects and whose keys are NodeKey objects. 11 1089-9 CH11 6/26/01 7:36 AM Page 386 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 387 11.2 The NodeKey Class n The BonNode objects can represent XML elements together with their attributes and text content. n The NodeKey objects, which simulate three “key columns” ina database table, can map the hierarchical relationships between the XML elements and facilitate some optimized data-access operations. In the rest of this chapter, our discussion of ForestHashtable will focus less on its the- oretical aspects and more on its practical aspects. Here is a list of some major areas we will cover: n Access to BonNode objects ina ForestHashtable can be optimized by caching some of the keys that are used to store them.We will discuss two such optimiza- tion mechanisms that we have developed. n To make it useful, we added some methods to the ForestHashtable class.These methods include those for adding, deleting, and editing the BonNode objects kept ina ForestHashtable . Here as elsewhere, we find techniques for optimizing the performance of these common tasks. n To apply other XML technologies, especially XSLT, to our ForestHashtable data, we develop a way to retrieve these data ina manner that obeys the rules of XML. n The bonForum Web chat application uses an instance of the ForestHashtable class, called bonForumXML .We will show you how the data in bonForumXML is ini- tialized, and we also will discuss an example of bonForumXML data after a couple chats were started. 11.2 The NodeKey Class The following excerpt from the file NodeKey.java is the definition of the NodeKey class: class NodeKey { String aKey; String bKey; String cKey; public NodeKey() { this.aKey = “”; this.bKey = “”; this.cKey = “”; } public String toString() { return aKey + “.” + bKey + “.” + cKey; } } As you can see, a NodeKey instance simply encapsulates three strings, which together form a three-part key.The three parts are known as aKey , bKey , and cKey . Its construc- 11 1089-9 CH11 6/26/01 7:36 AM Page 387 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 388 Chapter 11 XML Data Storage Class: ForestHashtable tor initializes these to empty strings, so we never need to check for a null value in any part of the triple-key value. 11.2.1 Using Unique Triple-Key Values A NodeKey , when converted to a string by the toString() method, is simply the three strings separated by period characters. An example of a NodeKey as a string is the following: “ 963539545905.963539545895.963539545885 ” NodeKeys such as these are used to represent the hierarchical relationships between BonNodes ina ForestHashtable .This is explained next, together with a discussion of the reasons for using these triple keys. 11.2.2 Timestamps for Order and Uniqueness The important thing to note for now is that the first string of 12 digits (the aKey ) is different for each NodeKey instance, something that allows each NodeKey object to function as a unique key for a BonNode object in the ForestHashtable .The aKey is derived from the system time in milliseconds, which gives a way to order NodeKeys in time and also ensures that each NodeKey can be given a unique value, as long as only one source of NodeKey values is present. 11.3 The BonNode Class Here is the definition of the BonNode class, from the file BonNode.java: class BonNode { NodeKey nodeKey; NodeKey parentNodeKey; boolean deleted; // flag as deleted, for quick deletes boolean flagged; // general purpose state flag String nodeName; // name of element String nodeAttributes; // attributes of element String nodeContent; // text between opening and closing tags } 11.3.1 NodeKey ina BonNode The NodeKey that is used to retrieve a BonNode from the ForestHashtable is also kept inside the BonNode instance itself, as the NodeKey member. If a BonNode is a child of another BonNode , then the NodeKey of the parent is kept in the parentNodeKey mem- ber. From these two NodeKeys kept in the BonNode , we can determine hierarchical rela- tionships between BonNode objects from the objects themselves. 11 1089-9 CH11 6/26/01 7:36 AM Page 388 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 389 11.3 The BonNode Class 11.3.2 parentNodeKey ina BonNode Note that the BonNode string member known as parentNodeKey is not needed for rep- resenting the hierarchical position of a node, as long as the NodeKey member is a mul- tipart key object, such as the triple-key values that we use in the bonForum project and which are discussed fully later. Why is the parentNodeKey in the BonNode class, then? There are two reasons for that. (Hint:You might want to revisit these two items after reading about forest tables.) 1. You could use the BonNode class with different types of keys that are not multi- ple-valued, like the double and triple-key examples. In that case, the two mem- bers NodeKey and parentNodeKey determine the hierarchical position of the node. 2. If you have used a triple-valued key (discussed later) in each of the two mem- bers NodeKey and parentNodeKey , then you will have fast access to the parent, grandparent, and great-grandparent above the current node that is represented by any BonNode . Of course, this would be done through methods, such as node.getParent().getGrandParent() . 11.3.3 Name of a BonNode A BonNode is designed to represent a node ina tree. Sometimes in this book, you might find the term node used rather loosely to refer to a BonNode .A BonNode is used in the bonForum project to represent three types of XML nodes. An XML element is mappable to the name that appears in an opening tag and its matching closing tag (if any) of an XML document.The only thing that the BonNode must keep to faithfully map an XML element node is its hierarchical position (in the NodeKey member) and its name (in the nodeName string member). 11.3.4 Attributes of a BonNode From a low-level XML programming view, it is advantageous to access the attributes of an element as child nodes of the element node that they are attributes of. So, attrib- utes are best represented as nodes in their own right, so to speak. Such “attribute nodes” would have to be specialized in some fashion, of course, to distinguish them from true children and ensure that the original XML could be reproduced. However, for the purposes of the bonForum Web application, all that is needed is to keep the list of name=value items associated with the associated XML element. A BonNode object keeps such a list as a single string member of itself, which is called nodeAttributes . 11.3.5 Content of a BonNode The third thing that a BonNode can represent from an XML document is a concatena- tion of all the text nodes that are children of the element named by the nodeName string member.The concatenated text is kept in the nodeContent string member of the BonNode . 11 1089-9 CH11 6/26/01 7:36 AM Page 389 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 390 Chapter 11 XML Data Storage Class: ForestHashtable 11.3.6 Background Deletion of a BonNode By using the flag called deleted , we intend to implement delayed deletion of nodes. The deleteNode() method will have to be changed so that it sets this flag value to true ina node instead of deleting the node. A background task could periodically purge nodes marked for deletion. As an added advantage, we could implement an unDoNodeDeletion() method. Node deletion comes in two “flavors.” In the first, or “leaf-only” version, it can avoid deletion of nodes that have children. In the second, or “recursive” version, it can delete all descendants (if any) of any node deleted. Note that in the ForestHashtable design (as opposed to a simple Java object hierarchy), it is necessary to explicitly check for parentNode references to the deleted object to carry out either type of deletion. For a fuller discussion as it relates to foreground instead of background deletion, see Section 11.7.4, “Deleting Descendants or Only Leaf Nodes.” 11.3.7 Flagging Visits to a BonNode Another flag in each node is called flagged .This is used by the getXMLForest() method that converts the data ina ForestHashtable into XML trees.This conversion requires repeated iterations of the Hashtable contents, first to get the root nodes, then to get their children, and finally to recursively visit all the other nodes.We “hide” each node that has already been processed by setting its flagged member to a value of True . This enables us to simplify the code that we use to test the depth of a node in the hierarchy. Someone might raise the objection that this is mixing procedural with OOP and can introduce multithreading and data integrity problems, and that it would be much safer to have this method keep its own separate list of nodeKeys visited and check against that.We hope that this objection will no longer hold when our simulation (the ForestHashtable class) is implemented ina relational database.The getXMLForest() method should be seen as a convenience for the simulation and not essential to the design. 11.4 ForestHashtable Maps Data Trees The ForestHashtable class is designed to simulate a database table that uses three columns as key values.You can implement the same functionality as the ForestHashtable class by creating such a table within any one of the many available databases together with some methods that can also be programmed as stored proce- dures within the database or within one or more Java classes.The ForestHashtable class is simply a simulation of such a database setup. 11 1089-9 CH11 6/26/01 7:36 AM Page 390 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 391 11.4 ForestHashtable Maps Data Trees 11.4.1 Design of the ForestHashtable Many of the advantages of using a database table with three keys to represent hierar- chical data structure are not utilized by the Web application project in this book. Therefore, you might wonder why such a design was implemented at all.We will briefly discuss the reasons in this section. 11.4.2 Hierarchical Data Representation A hierarchy, or tree structure, is commonly implemented in software by using just one variable to create links between the node objects of the tree. Each node object con- tains a member that acts as a pointer or key to its parent node. Because each node has only one parent node, such an arrangement can represent the entire tree, and methods can be created to add, edit, delete, traverse, and otherwise manipulate its node objects. 11.4.3 Forest Tables Using Two Keys A database table can be used to hold such hierarchical data. Each row represents a data node. Each node uses one column to contain a primary key that uniquely identifies that node. A second key column contains the primary key of a different row in the table, the one that represents that node’s parent. If a node has no parent, then it is a root node.The parent key of a root node is set to point to the root node itself.Therefore, if the values of the node and parent key are equal, the node in question is a root node. Usually, in Java APIs, the parent of a root node is null—that is, it represents the absence of a parent. Notice that making the par- ent equal to the node means that to traverse a tree, you cannot use this “usual” phrase: for (node = someNode; node.getParent() != null; node = node.getParent()){…} Neither can you use this stock phrase: while ((node = node.getParent()) != null){…} Instead, for tree traversal, you would use this: while (node != node.getParent()) {…} These examples were cited as a source of potential confusion stemming from our design. However, it does seem to us that the third example is simpler, at least. Let’s use an example to help you visualize such a table.We call the two keys node and parent , and we give each node just two columns for a name and type. For pri- mary key values we will use sequential integers. First we will display part of the table in Table 11.1. 11 1089-9 CH11 6/26/01 7:36 AM Page 391 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... nodeNameHashtable, is public PathNameHashtable pathNameHashtable = new PathNameHashtable(); As with the NodeNameHashtable class, you can see that this cache is an instance of a class (PathNameHashtable) that has been defined to extend java.util.Hashtable, but it adds nothing else to that class Again, this has been done only to make the pathNameHashtable variable available from JSP tags BonForumEngine... that we must find instead of making many new requests from a database Climbing Up the Hierarchy In the opposite direction, the ForestHashtable can more quickly find the parent of a node (if available) and the grandparent of a node (if available).This might not be important if the parent can be retrieved quickly and used in turn to find the grandparent However, there may be cases in which small savings... ForestHashtable, the three keys are called aKey, bKey, and cKey instead of node, parent, and grandparent grandparent Note Table 11.2 Tree of Life in a Triple-Key Table Node Parent Grandparent Name Type 1 2 1 1 1 1 Animalia Mollusca Kingdom Phylum 3 1 1 Chordata Phylum 4 3 1 Mammalia Class 5 4 3 Primates Order 6 2 1 Gastropoda Class 7 4 3 Carnivora Order 8 7 4 Hominidae Family 9 3 1 Reptilia Class 10... public NodeNameHashtable nodeNameHashtable = new NodeNameHashtable(); Notice that a class called NodeNameHashtable has been defined that extends java.util.Hashtable but that adds nothing to that class.This has been done solely to make the variable available from JSP tags Users Only Add Children of Nonroot Nodes In Section 8.6, “The add() Method,” of Chapter 8, “Java Servlet in Charge: BonForumEngine,” we... start and end tags, to make a more informative document.We are keeping it simple, though, to better show how XML can be stored in a database table . relational database. Certainly, that would not have been as difficult as creating the ForestHashtable class in Java, right? Questions are also raised about. PathNameHashtable(); As with the NodeNameHashtable class, you can see that this cache is an instance of a class ( PathNameHashtable ) that has been defined