Building and Running the Project

   

The catalog viewer project is available on the CD that accompanies this book. Copy the project directory from the CD to your hard disk and then go to the command line and change to the root of the project. You can run the catalog viewer with the catalog command (see Figure 1.10).

Figure 1.10. Running the catalog viewer.

graphics/01fig10.gif

Caution

You need a version of Java 2 (JDK 1.2 or above) installed on your machine to run this project. The project should run on JDK 1.1, but you will need to adapt the catalog.bat file.

You also need a SAX 2.0 “compliant XML parser to run this project. The project on the accompanying CD uses Xerces, which is available on the CD and from http://xml.apache.org.

If you switch to another parser, you will need to update PARSER_NAME in CatalogViewer .


Pattern Benefits

The major benefits of the builder and visitor patterns are as follows :

  • They separate reading and writing XML documents from the object structure.

  • They centralize the XML-related code in a few classes that simplify maintenance. This is particularly valuable in large projects where one developer is responsible for the object structure and another one is in charge of XML- related aspects.

Replacing the Director

The benefit of adopting a flexible design is that it is simple to change the application. For example, you can

  • Change the structure of the XML document by adapting the director (and the visitor) with no changes whatsoever to the object structure.

  • Only load a subset of the catalog, to save memory, by adapting the builder to discard those objects you don't need. Again, changes are limited to one class.

  • Replace the SAX parser with a DOM parser or even a database by adapting the director. Again, changes do not impact other classes.

Listing 1.15 demonstrates the last advantage. As the name implies, the DOMDirector is a director built on a DOM parser. This director makes exactly the same calls to the builder, so changes are really limited to one class!

Although a DOM parser is less efficient, because it uses more memory, it might be the only parser available to you.

Listing 1.15 DOMDirector.java
 package com.psol.catalog; import org.w3c.dom.*; public class DOMDirector {    protected CatalogBuilder builder;    public DOMDirector(CatalogBuilder builder)    {       this.builder = builder;    }    public void walkDocument(Document document)    {       Element el = document.getDocumentElement();       if(el.getTagName().equals("Catalog"))          walkCatalog(el);    }    public void walkCatalog(Element element)    {       NodeList children = element.getChildNodes();       for(int i = 0;i < children.getLength();i++)       {          Node node = children.item(i);          if(node.getNodeType() == Node.ELEMENT_NODE)          {             Element el = (Element)node;             if(el.getTagName().equals("Product"))                walkProduct(el);          }       }       builder.buildCatalog();    }    public void walkProduct(Element element)    {       NodeList children = element.getChildNodes();       String text = null,              image = null;       for(int i = 0;i < children.getLength();i++)       {          Node node = children.item(i);          if(node.getNodeType() == Node.ELEMENT_NODE)          {             Element el = (Element)node;             if(el.getTagName().equals("Text"))                text = extractContent(el);             else if(el.getTagName().equals("Image"))                image = extractContent(el);             else if(el.getTagName().equals("Descriptions"))                walkDescriptions(el);          }       }       String id = element.getAttribute("id"),              st = element.getAttribute("checked");       boolean checked = Boolean.valueOf(st).booleanValue();       if(null == image)          builder.buildTextualProduct(text,id,checked);       else          builder.buildVisualProduct(text,id,checked,image);    }    public void walkDescriptions(Element element)    {       NodeList children = element.getChildNodes();       for(int i = 0;i < children.getLength();i++)       {          Node node = children.item(i);          if(node.getNodeType() == Node.ELEMENT_NODE)          {             Element el = (Element)node;             if(el.getTagName().equals("Text"))             {                String text = extractContent(el),                       lang = el.getAttribute("xml:lang");                builder.buildDescription(lang,text);             }          }       }    }    public String extractContent(Element element)    {       // currently ignores entities, CDATA section, etc.       element.normalize();       Node child = element.getFirstChild();       if(child != null && child.getNodeType() == Node.TEXT_NODE)       {          Text text = (Text)child;          return text.getData();       }       else          return null;    } } 

Replacing the Visitor

The catalog viewer saves the complete catalog so the customer must email a file that is larger than required. However, it would be more efficient to save a smaller file with the list of products the customer selected.

This is easy to accomplish by writing a new visitor class, such as the XMLRequestVisitor shown in Listing 1.16.

Listing 1.16 XMLRequestVisitor.java
 package com.psol.catalog; import java.io.*; public class XMLRequestVisitor    implements CatalogVisitor {    protected PrintWriter pw;    public XMLRequestVisitor(PrintWriter pw)    {       this.pw = pw;    }    public void visitCatalog(Catalog catalog)       throws IOException    {       pw.println("<?xml version='1.0'?>");       pw.println("<Request>");       for(int i = 0;i < catalog.getSize();i++)          catalog.productAt(i).accept(this);       pw.print("</Request>");       pw.flush();    }    public void visitVisualProduct(VisualProduct product)       throws IOException    {       visitProduct(product);    }    public void visitTextualProduct(TextualProduct product)       throws IOException    {       visitProduct(product);    }    public void visitProduct(Product product)       throws IOException    {       if(product.isChecked())       {          pw.print("<Product id='");          // works with any Writer encoding but EBCDIC          String value = product.getId();          for(int i = 0;i < value.length();i++)          {             char c = value.charAt(i);             if(c == '\ '')                pw.print("&apos;");             else if(c == '&')                pw.print("&amp;");             else if(c > '\ u007f')             {                pw.print("&#");                pw.print(Integer.toString(c));                pw.print(';');             }             else                pw.print(c);          }          pw.println("\ '/>");       }    }    public void visitDescription(Description description)       throws IOException       { } } 
   


Applied XML Solutions
Applied XML Solutions
ISBN: 0672320541
EAN: 2147483647
Year: 1999
Pages: 142

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net