rdonkin     02/01/10 14:34:05

  Modified:    src/java/org/apache/ecs/examples HtmlTree.java
  Log:
  Christian Brensing <[EMAIL PROTECTED]> submitted an improved version of his ecs example
  
  Revision  Changes    Path
  1.2       +900 -640  jakarta-ecs/src/java/org/apache/ecs/examples/HtmlTree.java
  
  Index: HtmlTree.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ecs/src/java/org/apache/ecs/examples/HtmlTree.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HtmlTree.java     6 Nov 2001 23:09:49 -0000       1.1
  +++ HtmlTree.java     10 Jan 2002 22:34:05 -0000      1.2
  @@ -1,640 +1,900 @@
  -/*
  - * Copyright (c) 1999 The Java Apache Project.  All rights reserved.
  - *
  - * Redistribution and use in source and binary forms, with or without
  - * modification, are permitted provided that the following conditions
  - * are met:
  - *
  - * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer.
  - *
  - * 2. Redistributions in binary form must reproduce the above copyright
  - *    notice, this list of conditions and the following disclaimer in
  - *    the documentation and/or other materials provided with the
  - *    distribution.
  - *
  - * 3. All advertising materials mentioning features or use of this
  - *    software must display the following acknowledgment:
  - *    "This product includes software developed by the Java Apache 
  - *    Project. <http://java.apache.org/>"
  - *
  - * 4. The names "Java Apache Element Construction Set", "Java Apache ECS" and 
  - *    "Java Apache Project" must not be used to endorse or promote products 
  - *    derived from this software without prior written permission.
  - *
  - * 5. Products derived from this software may not be called 
  - *    "Java Apache Element Construction Set" nor "Java Apache ECS" appear 
  - *    in their names without prior written permission of the 
  - *    Java Apache Project.
  - *
  - * 6. Redistributions of any form whatsoever must retain the following
  - *    acknowledgment:
  - *    "This product includes software developed by the Java Apache 
  - *    Project. <http://java.apache.org/>"
  - *    
  - * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
  - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  - * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
  - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  - * OF THE POSSIBILITY OF SUCH DAMAGE.
  - *
  - * This software consists of voluntary contributions made by many
  - * individuals on behalf of the Java Apache Project. For more information
  - * on the Java Apache Project please see <http://java.apache.org/>.
  - *
  - */
  -
  -package org.apache.ecs.examples;
  -
  -import java.io.*;
  -import java.util.*;
  -import javax.swing.tree.*;
  -import org.apache.ecs.xml.*;
  -import org.apache.ecs.html.*;
  -
  -/**
  - * This JavaBean returns the hierarchical structure described in a
  - * javax.swing.tree.DefaultMutableTreeNode as valid XHTML. This class
  - * is a very simple counterpart of the javax.swing.JTree with the
  - * exception that the external Controller is integrated into this View.
  - * If you want your tree elements (nodes and leafs) to be marked with an
  - * anchor, you'll have to make sure that the name of your node contains
  - * such an anchor.
  - *
  - * <p>You can use this class in a JavaServerPage like this:</p>
  - *
  - * <p><blockquote>
  - *    <p>...template text...</p>
  - *    <p><code>
  - *      &lt;%-- Get the bean from the request scope or
  - *      create a new one if none exits --%&gt;<br />
  - *      &lt;jsp:useBean id="tree" scope="request"
  - *      class="org.apache.ecs.examples.HtmlTree"&gt;
  - *      <blockquote>
  - *        <p>&lt;%-- Read the path from the request --%&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="path" param="path" /&gt;</p>
  - *        <p>&lt;%-- Set bean properties --%&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="rootVisible" value="true" /&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="indentation" value="2" /&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="openIcon" value="open.gif" /&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="closedIcon" value="closed.gif" /&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="leafIcon" value="leaf.gif" /&gt;</p>
  - *        <p>&lt;%-- Workaround for Netscape
  - *        and Opera browsers --%&gt;<br />
  - *        &lt;jsp:setProperty name="tree"
  - *        property="action" value="tree.jsp" /&gt;</p>
  - *      </blockquote>
  - *      &lt;/jsp:useBean&gt;
  - *    </code></p>
  - *    <p>...template text...</p>
  - *    <p><code>
  - *      &lt;%-- Get the XHTML output from the bean --%&gt;<br />
  - *      &lt;jsp:getProperty name="tree" property="html" /&gt;
  - *    </code></p>
  - * </blockquote></p>
  - *
  - * Although this class is just an example of using parts of the Element
  - * Construction Set, you can use it quite well in real web applications.
  - *
  - * @version 1.0, 2001/10/30
  - * @author <a href="mailto:[EMAIL PROTECTED]";>Christian Brensing</a>
  - */
  -public class HtmlTree implements Serializable {
  -
  -  /**
  -   * Number of blank spaces around each hierarchical level
  -   * will be indented in relation to its parent node.
  -   * Default is 2.
  -   */
  -  protected int indentation = 2;
  -
  -  /**
  -   * Path to the requested node to be displayed,
  -   * described as colon separated integer values.
  -   * Default is an empty String.
  -   */
  -  protected String path = new String();
  -
  -  /**
  -   * Parameter name used to build the query string for the
  -   * anchor that acts as the Controller for opening and
  -   * closing nodes. Default is &quot;path&quot;.
  -   */
  -  protected String parameterName = new String("path");
  -
  -  /**
  -   * Array that stores the index of each node
  -   * read from the path property.
  -   */
  -  private int[] pathArray = new int[0];
  -
  -  /**
  -   * Icon for displaying leafs.
  -   * Default is an empty String.
  -   */
  -  protected String leafIcon = new String();
  -
  -  /**
  -   * Icon for displaying open nodes.
  -   * Default is an empty String.
  -   */
  -  protected String openIcon = new String();
  -
  -  /**
  -   * Icon for displaying closed nodes.
  -   * Default is an empty String.
  -   */
  -  protected String closedIcon = new String();
  -
  -  /**
  -   * Context path of a web resource for the workaround
  -   * of a strange behaviour of Netscape and Opera
  -   * browsers. Default is an empty String.
  -   */
  -  protected String action = new String();
  -
  -  /**
  -   * True if the root node is displayed, false if
  -   * its children are the highest visible nodes.
  -   * Default is true.
  -   */
  -  protected boolean rootVisible = true;
  -
  -  /**
  -   * The node that defines the tree displayed by this object.
  -   * Default is a sample model.
  -   */
  -  protected DefaultMutableTreeNode root = getDemoModel();
  -
  -  /**
  -   * Stores the requested node to be displayed.
  -   * Default is the root node.
  -   */
  -  private DefaultMutableTreeNode displayNode = root;
  -
  -  /**
  -   * Returns a HtmlTree with a sample model.
  -   */
  -  public HtmlTree() {
  -  } // Constructor
  -
  -  /**
  -   * Returns a HtmlTree with the specified DefaultMutableTreeNode
  -   * as its root. If the DefaultMutableTreeNode is <tt>null</tt>,
  -   * a sample model is set automatically.
  -   *
  -   * @param root a DefaultMutableTreeNode object
  -   */
  -  public HtmlTree(DefaultMutableTreeNode root) {
  -
  -    setRoot(root);
  -
  -  } // Constructor
  -
  -  /**
  -   * Sets the root node that will provide the data. If the
  -   * specified DefaultMutableTreeNode is <tt>null</tt>,
  -   * a sample model is set automatically.
  -   *
  -   * @param root a DefaultMutableTreeNode object
  -   */
  -  public void setRoot(DefaultMutableTreeNode root) {
  -
  -    // Check property
  -    if (root == null) { root = getDemoModel(); }
  -
  -    // Set property
  -    this.root = root;
  -
  -  } // setRoot
  -
  -  /**
  -   * Sets the path - described as colon separated integer values -
  -   * to the requested node to be displayed.
  -   *
  -   * @param path the path to the requested node to be displayed
  -   */
  -  public void setPath(String path) {
  -
  -    // Check property
  -    if (path == null) { path = new String(); }
  -
  -    // Set property
  -    this.path = path;
  -
  -    // Tokenize the path
  -    StringTokenizer st = new StringTokenizer(path,":");
  -
  -    // Reset path array
  -    pathArray = new int[st.countTokens()];
  -
  -    // Save value of each token in the array
  -    if (st.countTokens() > 0) {
  -      for (int i = 0; i <= st.countTokens(); i++) {
  -        pathArray[i] = Integer.
  -        parseInt(st.nextToken().trim());
  -      } // next i
  -    } // end if
  -
  -  } // setPath
  -
  -  /**
  -   * Returns a path constructed from the path array for the
  -   * specified level.
  -   *
  -   * @param level the distance from the node to the root node.
  -   * @return the path for the specified level
  -   */
  -  private String getPath(int level) {
  -
  -    // New StringBuffer for the path generation
  -    StringBuffer autoPath = new StringBuffer();
  -
  -    // For each node
  -    for (int i = 0; i < level; i++) {
  -
  -      // Add node index (read from the path array)
  -      autoPath.append(pathArray[i]);
  -
  -      // Add path separator (colon)
  -      if (i < (level - 1)) { autoPath.append(":"); }
  -
  -    } // next i
  -
  -    // Return generated path
  -    return autoPath.toString();
  -
  -  } // getPath
  -
  -  /**
  -   * Sets the name of the parameter used to build the query
  -   * string for the anchor that acts as the Controller for
  -   * opening and closing nodes. You only have to set this
  -   * name when the default name &quot;path&quot; is already
  -   * used by your web application.
  -   *
  -   * @param parameterName the name of the parameter used to
  -   * build the query string
  -   */
  -  public void setParameterName(String parameterName) {
  -
  -    // Check property
  -    if (parameterName == null ||
  -    parameterName.equals("")) {
  -    parameterName = new String("path"); }
  -
  -    // Set property
  -    this.parameterName = parameterName;
  -
  -  } // setParameterName
  -
  -  /**
  -   * Returns the name of the parameter used to build the
  -   * query string for the anchor that acts as the Controller
  -   * for opening and closing nodes.
  -   *
  -   * @return the name of the parameter
  -   */
  -  public String getParameterName() {
  -
  -    return parameterName;
  -
  -  } // getParameterName
  -
  -  /**
  -   * Determines whether or not the root node is visible.
  -   *
  -   * @param rootVisible true if the root node of the tree
  -   * is to be displayed
  -   */
  -  public void setRootVisible(boolean rootVisible) {
  -
  -    this.rootVisible = rootVisible;
  -
  -  } // setRootVisible
  -
  -  /**
  -   * Returns true if the root node of the tree is displayed.
  -   *
  -   * @return true if the root node of the tree is displayed
  -   */
  -  public boolean isRootVisible() {
  -
  -    return rootVisible;
  -
  -  } // isRootVisible
  -
  -  /**
  -   * Sets the number of blank spaces around each hierarchical
  -   * level will be indented in relation to its parent node.
  -   *
  -   * @param indentation the number of blank spaces
  -   */
  -  public void setIndentation(int indentation) {
  -
  -    this.indentation = indentation;
  -
  -  } // setIndentation
  -
  -  /**
  -   * Sets the icon for displaying open nodes.
  -   *
  -   * @param openIcon the URI of an image file
  -   */
  -  public void setOpenIcon(String openIcon) {
  -
  -    this.openIcon = openIcon;
  -
  -  } // setOpenIcon
  -
  -  /**
  -   * Sets the icon for displaying closed nodes.
  -   *
  -   * @param closedIcon the URI of an image file
  -   */
  -  public void setClosedIcon(String closedIcon) {
  -
  -    this.closedIcon = closedIcon;
  -
  -  } // setClosedIcon
  -
  -  /**
  -   * Sets the icon for displaying leafs.
  -   *
  -   * @param leafIcon the URI of an image file
  -   */
  -  public void setLeafIcon(String leafIcon) {
  -
  -    this.leafIcon = leafIcon;
  -
  -  } // setLeafIcon
  -
  -  /**
  -   * Workaround of a strange behaviour of Netscape and Opera browsers.
  -   * In these browsers the relative URL containg only the query string
  -   * with the path information (e.g. &quot;?path=0:1&quot;) are not
  -   * translated correctly into an absoulte URL. By setting a context
  -   * path, on which to append the query string, this behaviour should
  -   * be fixed.
  -   *
  -   * @param action the context path of a web resource (e.g. a JSP-File)
  -   */
  -  public void setAction(String action) {
  -
  -    this.action = action;
  -
  -  } // setAction
  -
  -  /**
  -   * Returns the name of the currently expanded node to
  -   * be displayed.
  -   *
  -   * @return the name of the node to be displayed
  -   */
  -  public String getNodeName() {
  -
  -    return expand().toString();
  -
  -  } // getNodeName
  -
  -  /**
  -   * Constructs a valid XHTML &lt;img&gt;-tag from the specified icon.
  -   * Although this method uses the xml-package to generate a valid tag,
  -   * the xhtml-package would provide the same functionality.
  -   *
  -   * @param icon the URI of an image file
  -   * @return a valid XHTML &lt;img&gt;-tag
  -   */
  -  private String getImg(String icon) {
  -
  -    // New <img>
  -    XML img = new XML("img",false);
  -
  -    // Check specified icon property
  -    if (icon == null) { icon = new String(); }
  -
  -    // Set src attribute
  -    img.addAttribute("src",icon);
  -
  -    // return <img>
  -    return img.toString();
  -
  -  } // getImg
  -
  -  /**
  -   * Expands the tree by following the specified path
  -   * and returns the requested node to be displayed
  -   *
  -   * @return the requested node to be displayed
  -   */
  -  private DefaultMutableTreeNode expand() {
  -
  -    // Reset node to be displayed
  -    displayNode = root;
  -
  -    // Iterate trough the path array
  -    for (int i = 0; i < pathArray.length; i++) {
  -      displayNode = (DefaultMutableTreeNode)
  -      displayNode.getChildAt(pathArray[i]);
  -    } // next i
  -
  -    // Return node to be displayed
  -    return displayNode;
  -
  -  } // expand
  -
  -  /**
  -   * Returns the hierarchical structure described in the specified root
  -   * node as valid XHTML. For perfomance reasons all parent nodes of the
  -   * requested node are collapsed. The source code does not contain any
  -   * formatting tags or attributes. I recommend that you use Cascading
  -   * Style Sheets instead. For this purpose, the tree elements are marked
  -   * with the class attribute values &quot;tree&quot;, &quot;parent&quot;
  -   * and &quot;child&quot;.
  -   *
  -   * @return the hierarchical structure within a &lt;table&gt;-tag
  -   */
  -  public String getHtml() {
  -
  -    // Expand the tree
  -    displayNode = expand();
  -
  -    // New <table>
  -    Table table = new Table();
  -    table.setClass("tree");
  -
  -    // Reset auto indentation
  -    int autoIndentation = 0;
  -
  -    // Initialize ancestor node with the first
  -    // child of the node to be displayed
  -    TreeNode ancestor = displayNode.getFirstChild();
  -
  -    // Read all ancestors into an array
  -    ArrayList list = new ArrayList();
  -    while ((ancestor = ancestor.getParent())
  -    != null) { list.add(ancestor); }
  -
  -    // For each ancestor (ordered desc beginning at the root)
  -    for (int index = list.size(); index > 0; index--) {
  -
  -      // Get current ancestor
  -      DefaultMutableTreeNode parent =
  -      (DefaultMutableTreeNode)list.
  -      get(index-1);
  -
  -      // Displays the ancestor if it's not the root
  -      // or the isRootVisible property is set to true
  -      if (!parent.isRoot() || rootVisible) {
  -
  -        // New <td>
  -        TD td = new TD();
  -        td.setClass("parent");
  -
  -        // Generate href for this ancestor (the
  -        // level is decreased by one to provide
  -        // an anchor to its parent node)
  -        String href = action.concat("?").
  -        concat(parameterName).concat("=").
  -        concat(getPath(parent.getLevel()-1));
  -
  -        // Add indentation to <td>
  -        for (int i = 0; i < autoIndentation; i++)
  -        { td.addElement("&nbsp;"); }
  -
  -        // Add icon with <a> to <td>
  -        td.addElement(new A(href,getImg(openIcon)));
  -
  -        // Add ancestor with <nobr> to <td>
  -        td.addElement(new NOBR(parent.toString()));
  -
  -        // Add <td> to <tr> to <table>
  -        table.addElement(new TR(td));
  -
  -        // Increment auto indentation
  -        autoIndentation = autoIndentation + indentation;
  -
  -      } // end if rootVisible
  -
  -    } // next index
  -
  -    // For each child
  -    for (int index = 0; index < displayNode.getChildCount(); index++) {
  -
  -      // New <td>
  -      TD td = new TD();
  -      td.setClass("child");
  -
  -      // Get current child
  -      DefaultMutableTreeNode child =
  -      (DefaultMutableTreeNode)displayNode.
  -      getChildAt(index);
  -
  -      // Generate path == path + child index
  -      String autoPath = getPath(child.getLevel()-1).
  -      concat(":").concat(String.valueOf(index));
  -
  -      // Generate href for this child
  -      String href = action.concat("?").
  -      concat(parameterName).concat("=").
  -      concat(autoPath);
  -
  -      // Add indentation to <td>
  -      for (int i = 0; i < autoIndentation; i++)
  -      { td.addElement("&nbsp;"); }
  -
  -      // New <img> with default leaf icon
  -      String img = getImg(leafIcon);
  -
  -      // Set closed node icon, if child is not a leaf
  -      if (!child.isLeaf()) { img = getImg(closedIcon); }
  -
  -      // Add icon with <a> (not for leafs) to <td>
  -      if (!child.isLeaf()) {td.addElement(new A(href,img)); }
  -
  -      // Add icon without <a> (leafs only) to <td>
  -      if (child.isLeaf()) { td.addElement(img); }
  -
  -      // Add child with <nobr> to <td>
  -      td.addElement(new NOBR(child.toString()));
  -
  -      // Add <td> to <tr> to <table>
  -      table.addElement(new TR(td));
  -
  -    } // next index
  -
  -    // Return <table>
  -    return table.toString();
  -
  -  } // getHtml
  -
  -  /**
  -   * Returns a sample tree model.
  -   *
  -   * @return a DefaultMutableTreeNode with a sample tree model
  -   */
  -  private DefaultMutableTreeNode getDemoModel() {
  -
  -    // New root node
  -    DefaultMutableTreeNode root =
  -    new DefaultMutableTreeNode("Root");
  -
  -    // First level
  -    for (int i = 1; i <= 5; i++) {
  -
  -      // New node
  -      DefaultMutableTreeNode child =
  -      new DefaultMutableTreeNode("Folder-" + i);
  -
  -      // Add node to root
  -      root.add(child);
  -
  -      // Second level
  -      for (int j = 1; j <= 3; j++) {
  -
  -        // New node
  -        DefaultMutableTreeNode subchild =
  -        new DefaultMutableTreeNode("Subfolder-" + j);
  -
  -        // Add node to parent node
  -        child.add(subchild);
  -
  -        // Third level
  -        for (int k = 1; k <= 3; k++) {
  -
  -          // New anchor
  -          A a = new A("http://jakarta.apache.org";);
  -          a.setTarget("target").addElement("Document-" + k);
  -
  -          // New node (leaf)
  -          DefaultMutableTreeNode document =
  -          new DefaultMutableTreeNode(a.toString());
  -
  -          // Add node to parent node
  -          subchild.add(document);
  -
  -        } // next k
  -
  -      } // next j
  -
  -    } // next i
  -
  -    // Return root node
  -    return root;
  -
  -  } // getDemoModel
  -
  -} // HtmlTree
  +/*
  + * Copyright (c) 1999 The Java Apache Project.  All rights reserved.
  + *
  + * Redistribution and use in source and binary forms, with or without
  + * modification, are permitted provided that the following conditions
  + * are met:
  + *
  + * 1. Redistributions of source code must retain the above copyright
  + *    notice, this list of conditions and the following disclaimer.
  + *
  + * 2. Redistributions in binary form must reproduce the above copyright
  + *    notice, this list of conditions and the following disclaimer in
  + *    the documentation and/or other materials provided with the
  + *    distribution.
  + *
  + * 3. All advertising materials mentioning features or use of this
  + *    software must display the following acknowledgment:
  + *    "This product includes software developed by the Java Apache
  + *    Project. <http://java.apache.org/>"
  + *
  + * 4. The names "Java Apache Element Construction Set", "Java Apache ECS" and
  + *    "Java Apache Project" must not be used to endorse or promote products
  + *    derived from this software without prior written permission.
  + *
  + * 5. Products derived from this software may not be called
  + *    "Java Apache Element Construction Set" nor "Java Apache ECS" appear
  + *    in their names without prior written permission of the
  + *    Java Apache Project.
  + *
  + * 6. Redistributions of any form whatsoever must retain the following
  + *    acknowledgment:
  + *    "This product includes software developed by the Java Apache
  + *    Project. <http://java.apache.org/>"
  + *
  + * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
  + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
  + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  + * OF THE POSSIBILITY OF SUCH DAMAGE.
  + *
  + * This software consists of voluntary contributions made by many
  + * individuals on behalf of the Java Apache Project. For more information
  + * on the Java Apache Project please see <http://java.apache.org/>.
  + *
  + */
  +
  +package org.apache.ecs.examples;
  +
  +import java.io.*;
  +import java.util.*;
  +import javax.swing.tree.*;
  +import org.apache.ecs.xml.*;
  +import org.apache.ecs.html.*;
  +
  +/**
  + * This JavaBean returns the hierarchical structure described in a
  + * javax.swing.tree.DefaultMutableTreeNode as valid XHTML. This class
  + * is a very simple counterpart of the javax.swing.JTree with the
  + * exception that the external Controller is integrated into this View.
  + * If you want your tree elements (nodes and leafs) to be marked with an
  + * anchor, you'll have to make sure that the name of your node contains
  + * such an anchor.
  + *
  + * <p>A specific node in a tree can be identified by a path, described as
  + * colon separated integer values (e.g. &quot;0:1&quot;). Unlike Swing's
  + * JTree component, this JavaBean expands only the requested node, leaving
  + * all its parent nodes collapsed. An <i>expanded</i> node is one displays
  + * its children. A <i>collapsed</i> node is one which hides them.</p>
  + *
  + * <p>You can use this class in a JavaServerPage like this:</p>
  + *
  + * <p><blockquote>
  + *    <p>...template text...</p>
  + *    <p><code>
  + *      &lt;%-- Get the bean from the request scope or
  + *      create a new one if none exists --%&gt;<br />
  + *      &lt;jsp:useBean id="tree" scope="request"
  + *      class="org.apache.ecs.examples.HtmlTree"&gt;
  + *      <blockquote>
  + *        <p>&lt;%-- Read the path from the request --%&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="path" param="path" /&gt;</p>
  + *        <p>&lt;%-- Set UI properties --%&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="rootVisible" value="true" /&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="indentation" value="2" /&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="openIcon" value="open.gif" /&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="closedIcon" value="closed.gif" /&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="leafIcon" value="leaf.gif" /&gt;</p>
  + *        <p>&lt;%-- Workaround for Netscape
  + *        and Opera browsers --%&gt;<br />
  + *        &lt;jsp:setProperty name="tree"
  + *        property="action" value="tree.jsp" /&gt;</p>
  + *      </blockquote>
  + *      &lt;/jsp:useBean&gt;
  + *    </code></p>
  + *    <p>...template text...</p>
  + *    <p><code>
  + *      &lt;%-- Get the XHTML output from the bean --%&gt;<br />
  + *      &lt;jsp:getProperty name="tree" property="html" /&gt;
  + *    </code></p>
  + * </blockquote></p>
  + *
  + * Although this class is just an example of using parts of the Element
  + * Construction Set, you can use it quite well in real web applications.
  + *
  + * @version 1.1, 2001/12/30, added ability to use a DefaultTreeModel as the
  + *                           data model, added some useful methods including
  + *                           one for basic HTML encoding, improved javadoc
  + *                           comments and fixed minor bugs
  + * @version 1.0, 2001/10/30, initial release
  + * @author <a href="mailto:[EMAIL PROTECTED]";>Christian Brensing</a>
  + */
  +public class HtmlTree implements Serializable
  +{
  +    /**
  +     * Number of blank spaces around each hierarchical level
  +     * will be indented in relation to its parent node.
  +     * Default is 2.
  +     */
  +    protected int indentation = 2;
  +    
  +    /**
  +     * Path to the requested node to be displayed,
  +     * described as colon separated integer values.
  +     * Default is an empty String.
  +     */
  +    protected String path = "";
  +    
  +    /**
  +     * Parameter name used to build the query string for the
  +     * anchor that acts as the Controller for opening and
  +     * closing nodes. Default is &quot;path&quot;.
  +     */
  +    protected String parameterName = "path";
  +    
  +    /**
  +     * Array that stores the index of each node
  +     * read from the path property.
  +     */
  +    private int[] pathArray = new int[0];
  +    
  +    /**
  +     * Icon for displaying leafs.
  +     * Default is an empty String.
  +     */
  +    protected String leafIcon = "";
  +    
  +    /**
  +     * Icon for displaying open nodes.
  +     * Default is an empty String.
  +     */
  +    protected String openIcon = "";
  +    
  +    /**
  +     * Icon for displaying closed nodes.
  +     * Default is an empty String.
  +     */
  +    protected String closedIcon = "";
  +    
  +    /**
  +     * Context path of a web resource for the workaround
  +     * of a strange behaviour of Netscape and Opera
  +     * browsers. Default is an empty String.
  +     */
  +    protected String action = "?";
  +    
  +    /**
  +     * True if the root node is displayed, false if
  +     * its children are the highest visible nodes.
  +     * Default is true.
  +     */
  +    protected boolean rootVisible = true;
  +    
  +    /**
  +     * The node that defines the tree displayed by this object.
  +     * Default is a sample model.
  +     */
  +    protected DefaultMutableTreeNode root = getDefaultTreeModel();
  +    
  +    /**
  +     * Stores the requested node to be displayed.
  +     * Default is the root node.
  +     */
  +    protected DefaultMutableTreeNode displayNode = root;
  +    
  +    /**
  +     * Returns a HtmlTree with a sample model.
  +     */
  +    public HtmlTree()
  +    {
  +        // do nothing
  +    }
  +    
  +    /**
  +     * Returns a HtmlTree with the specified DefaultMutableTreeNode
  +     * as its root. If the DefaultMutableTreeNode is <tt>null</tt>,
  +     * a sample model is set automatically.
  +     *
  +     * @param root a DefaultMutableTreeNode object
  +     */
  +    public HtmlTree(DefaultMutableTreeNode root)
  +    {
  +        setRoot(root);
  +    }
  +    
  +    /**
  +     * Returns a HtmlTree with the specified DefaultTreeModel as
  +     * its model. If the specified DefaultTreeModel is <tt>null</tt>,
  +     * a sample model is set automatically.
  +     *
  +     * @param model a DefaultTreeModel object
  +     */
  +    public HtmlTree(DefaultTreeModel model)
  +    {
  +        setModel(model);
  +    }
  +    
  +    /**
  +     * Sets the root node that will provide the data. If the
  +     * specified DefaultMutableTreeNode is <tt>null</tt>,
  +     * a sample model is set automatically.
  +     *
  +     * @param root a DefaultMutableTreeNode object
  +     */
  +    public void setRoot(DefaultMutableTreeNode root)
  +    {
  +        // Check property
  +        if (root == null) 
  +        { 
  +            root = getDefaultTreeModel(); 
  +        }
  +    
  +        // Set property
  +        this.root = root;
  +    }
  +    
  +    /**
  +     * Returns the node that defines the tree displayed
  +     * by this object.
  +     *
  +     * @return the root node that provides the data
  +     */
  +    public DefaultMutableTreeNode getRoot()
  +    {
  +        return root;
  +    }
  +    
  +    /**
  +     * Sets the tree model that will provide the data. If the
  +     * specified DefaultTreeModel is <tt>null</tt>, a sample
  +     * model is set automatically.
  +     *
  +     * @param model a DefaultTreeModel object
  +     */
  +    public void setModel(DefaultTreeModel model)
  +    {
  +        if (model != null)
  +        {
  +            setRoot((DefaultMutableTreeNode)
  +            model.getRoot());
  +        }
  +        else
  +        {
  +            setRoot(null);
  +        }
  +    }
  +    
  +    /**
  +     * Returns the model that defines the tree displayed
  +     * by this object.
  +     *
  +     * @return the model that provides the data
  +     */
  +    public DefaultTreeModel getModel()
  +    {
  +        return new DefaultTreeModel(root);
  +    }
  +    
  +    /**
  +     * Sets the path - described as colon separated integer values -
  +     * to the requested node to be displayed.
  +     *
  +     * @param path the path to the requested node to be displayed
  +     */
  +    public void setPath(String path)
  +    {
  +        try
  +        {
  +            // Tokenize the path
  +            pathArray = getPathResolved(path);
  +    
  +            // Set path property
  +            this.path = path;
  +        }
  +        catch (NumberFormatException nfe)
  +        {
  +            // Reset path property
  +            this.path = "";
  +        }
  +    }
  +    
  +    /**
  +     * Returns the path to the requested node.
  +     *
  +     * @return the path to the requested node
  +     */
  +    public String getPath()
  +    {
  +        return path;
  +    }
  +    
  +    /**
  +     * Returns a path constructed from the path array for the
  +     * specified level.
  +     *
  +     * @param level the distance from the node to the root node.
  +     * @return the path for the specified level
  +     */
  +    public String getPath(int level)
  +    {
  +        // Check property
  +        if (level > pathArray.length) 
  +        { 
  +            level = pathArray.length; 
  +        }
  +    
  +        // New StringBuffer for the path generation
  +        StringBuffer autoPath = new StringBuffer();
  +    
  +        // For each node
  +        for (int i = 0; i < level; i++)
  +        {
  +            // Add node index (read from the path array)
  +            autoPath.append(pathArray[i]);
  +        
  +            // Add path separator (colon)
  +            if (i < (level - 1)) 
  +            { 
  +                autoPath.append(":"); 
  +            }
  +        }
  +    
  +        // Return generated path
  +        return autoPath.toString();
  +    }
  +    
  +    /**
  +     * Returns an array that stores the index of each
  +     * node read from the specified path.
  +     *
  +     * @return an array of node indices
  +     * @throws java.lang.NumberFormatException if the specified
  +     * path does not consist of colon separated integer values
  +     */
  +    public static int[] getPathResolved(String path)
  +        throws NumberFormatException
  +    {
  +        try
  +        {
  +            // Initialize the token array
  +            int[] returnArray = new int[0];
  +        
  +            // Tokenize the path
  +            StringTokenizer st = new StringTokenizer(path,":");
  +        
  +            // Reset the array with the number of tokens
  +            returnArray = new int[st.countTokens()];
  +        
  +            // Save value of each token in the array
  +            if (st.countTokens() > 0)
  +            {
  +                for (int i = 0; i < returnArray.length; i++)
  +                {
  +                    returnArray[i] = Integer.parseInt
  +                        (st.nextToken().trim());
  +                }
  +            }
  +        
  +            // Return path array
  +            return returnArray;
  +        }
  +        catch (Exception e)
  +        {
  +            // Wrap the exception in a NumberFormatException
  +            throw new NumberFormatException(e.getMessage());
  +        }
  +    }
  +    
  +    /**
  +     * Sets the name of the parameter used to build the query
  +     * string for the anchor that acts as the Controller for
  +     * opening and closing nodes. You only have to set this
  +     * name if the default name &quot;path&quot; is already
  +     * used by your web application.
  +     *
  +     * @param parameterName the name of the parameter used
  +     * to build the query string
  +     */
  +    public void setParameterName(String parameterName)
  +    {
  +        // Check property
  +        if (parameterName == null
  +        || parameterName.equals(""))
  +        {
  +            parameterName = "path";
  +        }
  +    
  +        // Set property
  +        this.parameterName = parameterName;
  +    }
  +    
  +    /**
  +     * Returns the name of the parameter used to build the
  +     * query string for the anchor that acts as the Controller
  +     * for opening and closing nodes.
  +     *
  +     * @return the name of the parameter
  +     */
  +    public String getParameterName()
  +    {
  +        return parameterName;
  +    }
  +    
  +    /**
  +     * Determines whether or not the root node is visible.
  +     *
  +     * @param rootVisible true if the root node of the tree
  +     * is to be displayed
  +     */
  +    public void setRootVisible(boolean rootVisible)
  +    {
  +        this.rootVisible = rootVisible;
  +    }
  +    
  +    /**
  +     * Returns true if the root node of the tree is displayed.
  +     *
  +     * @return true if the root node of the tree is displayed
  +     */
  +    public boolean isRootVisible()
  +    {
  +        return rootVisible;
  +    }
  +    
  +    /**
  +     * Sets the number of blank spaces around each hierarchical
  +     * level will be indented in relation to its parent node.
  +     *
  +     * @param indentation the number of blank spaces
  +     */
  +    public void setIndentation(int indentation)
  +    {
  +        this.indentation = indentation;
  +    }
  +    
  +    /**
  +     * Returns the number of blank spaces around each
  +     * hierarchical level is indented in relation to
  +     * its parent node.
  +     *
  +     * @return the number of blank spaces
  +     */
  +    public int getIndentation()
  +    {
  +        return indentation;
  +    }
  +    
  +    /**
  +     * Returns the name of the currently expanded node.
  +     *
  +     * @return the name of the node
  +     */
  +    public String getNodeName()
  +    {
  +        return displayNode.toString();
  +    }
  +    
  +    /**
  +     * Returns the number of rows that are currently
  +     * being displayed.
  +     *
  +     * @return the number of rows
  +     */
  +    public int getRowCount()
  +    {
  +        // Get level of the node to be displayed
  +        int rowCount = displayNode.getLevel();
  +    
  +        // Add number of children
  +        rowCount = rowCount + displayNode.getChildCount();
  +    
  +        // Increment by 1 if the root node is being displayed
  +        if (rootVisible) 
  +        { 
  +            rowCount++; 
  +        }
  +    
  +        // Return number of rows
  +        return rowCount;
  +    }
  +    
  +    /**
  +     * Sets the icon for displaying open nodes.
  +     *
  +     * @param openIcon the URI of an image file
  +     */
  +    public void setOpenIcon(String openIcon)
  +    {
  +        this.openIcon = openIcon;
  +    }
  +    
  +    /**
  +     * Sets the icon for displaying closed nodes.
  +     *
  +     * @param closedIcon the URI of an image file
  +     */
  +    public void setClosedIcon(String closedIcon)
  +    {
  +        this.closedIcon = closedIcon;
  +    }
  +    
  +    /**
  +     * Sets the icon for displaying leafs.
  +     *
  +     * @param leafIcon the URI of an image file
  +     */
  +    public void setLeafIcon(String leafIcon)
  +    {
  +        this.leafIcon = leafIcon;
  +    }
  +    
  +    /**
  +     * Workaround of a strange behaviour of Netscape and Opera browsers.
  +     * In these browsers the relative URL containg only the query string
  +     * with the path information (e.g. &quot;?path=0:1&quot;) are not
  +     * translated correctly into an absoulte URL. By setting a context
  +     * path, on which to append the query string, this behaviour should
  +     * be fixed.
  +     *
  +     * @param action the context path of a web resource (e.g. a JSP-File)
  +     */
  +    public void setAction(String action)
  +    {
  +        // Check property
  +        if (action == null) 
  +        { 
  +            action = ""; 
  +        }
  +    
  +        // If the specified context path already contains
  +        // a query string, append an ampersand character
  +        // for further parameter concatenation
  +        if (action.indexOf("=") != -1)
  +        {
  +            action = action + "&";
  +        }
  +        else
  +        {
  +            action = action + "?";
  +        }
  +    
  +        // Set property
  +        this.action = action;
  +    }
  +    
  +    /**
  +     * Constructs a valid XHTML &lt;img&gt;-tag from the specified icon.
  +     * Although this method uses the xml-package to generate a valid tag,
  +     * the xhtml-package would provide the same functionality.
  +     *
  +     * @param icon the URI of an image file
  +     * @return a valid XHTML &lt;img&gt;-tag
  +     */
  +    public String getImg(String icon)
  +    {
  +        // New <img>
  +        XML img = new XML("img",false);
  +    
  +        // Check specified icon property
  +        if (icon == null) 
  +        { 
  +            icon = ""; 
  +        }
  +    
  +        // Set src attribute
  +        img.addAttribute("src",icon);
  +    
  +        // return <img>
  +        return img.toString();
  +    }
  +    
  +    /**
  +     * Expands the tree by following the specified path
  +     * and returns the requested node to be displayed.
  +     *
  +     * @return the requested node to be displayed
  +     */
  +    public DefaultMutableTreeNode getRequestedNode()
  +    {
  +        // Reset node to be displayed
  +        displayNode = root;
  +    
  +        // Iterate trough the path array
  +        for (int i = 0; i < pathArray.length; i++)
  +        {
  +            if (displayNode.getDepth() > 1)
  +            {
  +                displayNode = (DefaultMutableTreeNode)
  +                displayNode.getChildAt(pathArray[i]);
  +            }
  +        }
  +    
  +        // Return node to be displayed
  +        return displayNode;
  +    }
  +    
  +    /**
  +     * Returns the hierarchical structure described in the specified root
  +     * node as valid XHTML. For perfomance reasons all parent nodes of the
  +     * requested node are collapsed. The source code does not contain any
  +     * formatting tags or attributes. I recommend that you use Cascading
  +     * Style Sheets instead. For this purpose, the tree elements are marked
  +     * with the class attribute values &quot;tree&quot;, &quot;parent&quot;
  +     * and &quot;child&quot;.
  +     *
  +     * <p>A sample Style Sheet would look like this:</p>
  +     *
  +     * <p><blockquote>
  +     *   <code>
  +     *     a { color: black; text-decoration: none; }<br />
  +     *     a:hover { color: black; text-decoration: underline; }<br />
  +     *     img { margin-right: 5px; vertical-align: middle; border: none; }<br />
  +     *     table { font: normal 8pt Arial,Helvetica,sans-serif; }</br />
  +     *     td.parent { font-weight: bold; }<br />
  +     *   </code>
  +     * </blockquote></p>
  +     *
  +     * @return the hierarchical structure within a &lt;table&gt;-tag
  +     */
  +    public String getHtml()
  +    {
  +        // Expand the tree
  +        displayNode = getRequestedNode();
  +    
  +        // New <table>
  +        Table table = new Table();
  +        table.setClass("tree");
  +    
  +        // Reset auto indentation
  +        int autoIndentation = 0;
  +    
  +        // Initialize ancestor node with the first child of
  +        // the node to be displayed (for parent recursion)
  +        TreeNode ancestor = displayNode.getFirstChild();
  +    
  +        // Read all ancestors into an array
  +        ArrayList list = new ArrayList();
  +        while ((ancestor = ancestor.getParent()) != null)
  +        {
  +            list.add(ancestor);
  +        }
  +    
  +        // For each ancestor (ordered desc beginning at the root)
  +        for (int i = list.size(); i > 0; i--)
  +        {
  +            // Get current ancestor
  +            DefaultMutableTreeNode parent =
  +                (DefaultMutableTreeNode)list.get(i-1);
  +        
  +            // Displays the ancestor if it's not the root
  +            // or the rootVisible property is set to true
  +            if (!parent.isRoot() || rootVisible)
  +            {
  +                // New <td>
  +                TD td = new TD();
  +                td.setClass("parent");
  +        
  +                // Generate href for this ancestor (the
  +                // level is decreased by one to provide
  +                // an anchor to its parent node)
  +                String href = action + parameterName
  +                    + "=" + getPath(parent.getLevel()-1);
  +        
  +                // Add indentation to <td>
  +                for (int j = 0; j < autoIndentation; j++)
  +                {
  +                    td.addElement("&nbsp;");
  +                }
  +        
  +                // Add icon with <a> to <td>
  +                td.addElement(new A(href,getImg(openIcon)));
  +        
  +                // Add ancestor with <nobr> to <td>
  +                td.addElement(new NOBR(parent.toString()));
  +        
  +                // Add <td> to <tr> to <table>
  +                table.addElement(new TR(td));
  +        
  +                // Increment auto indentation
  +                autoIndentation = autoIndentation + indentation;
  +            }
  +        }
  +    
  +        // For each child
  +        for (int i = 0; i < displayNode.getChildCount(); i++)
  +        {
  +            // New <td>
  +            TD td = new TD();
  +            td.setClass("child");
  +        
  +            // Get current child
  +            DefaultMutableTreeNode child =
  +                (DefaultMutableTreeNode)displayNode
  +                .getChildAt(i);
  +        
  +            // Generate path == path + child index
  +            String autoPath = getPath(child
  +                .getLevel()-1) + ":" + i;
  +        
  +            // Trim leading colon
  +            if (autoPath.startsWith(":"))
  +            {
  +                autoPath = autoPath.substring(1);
  +            }
  +        
  +            // Generate href for this child
  +            String href = action + parameterName
  +                + "=" + autoPath;
  +        
  +            // Add indentation to <td>
  +            for (int j = 0; j < autoIndentation; j++)
  +            {
  +                td.addElement("&nbsp;");
  +            }
  +        
  +            // New <img> with default leaf icon
  +            String img = getImg(leafIcon);
  +        
  +            // Set closed node icon, if child is not a leaf
  +            if (!child.isLeaf()) 
  +            { 
  +                img = getImg(closedIcon); 
  +            }
  +        
  +            // Add icon with <a> (not for leafs) to <td>
  +            if (!child.isLeaf()) 
  +            {
  +                td.addElement(new A(href,img)); 
  +            }
  +        
  +            // Add icon without <a> (leafs only) to <td>
  +            if (child.isLeaf()) 
  +            { 
  +                td.addElement(img); 
  +            }
  +        
  +            // Add child with <nobr> to <td>
  +            td.addElement(new NOBR(child.toString()));
  +        
  +            // Add <td> to <tr> to <table>
  +            table.addElement(new TR(td));
  +        }
  +    
  +        // Return <table>
  +        return table.toString();
  +    }
  +    
  +    /**
  +     * Overrides <tt>toString()</tt> to print something meaningful.
  +     * Returns the hierarchical structure described in the specified
  +     * root node as valid XHTML.
  +     *
  +     * @see #getHtml
  +     */
  +    public String toString()
  +    {
  +        return getHtml();
  +    }
  +    
  +    /**
  +     * Creates and returns a sample tree model. Used primarily
  +     * during the design of the JavaServerPage to show something
  +     * interesting.
  +     *
  +     * @return a DefaultMutableTreeNode with a sample tree model
  +     */
  +    protected static DefaultMutableTreeNode getDefaultTreeModel()
  +    {
  +        // New root node
  +        DefaultMutableTreeNode root =
  +        new DefaultMutableTreeNode("Root");
  +    
  +        // First level
  +        for (int i = 1; i <= 5; i++)
  +        {
  +            // New node
  +            DefaultMutableTreeNode folder =
  +                new DefaultMutableTreeNode("Folder-" + i);
  +        
  +            // Add node to root
  +            root.add(folder);
  +        
  +            // Second level
  +            for (int j = 1; j <= 3; j++)
  +            {
  +                // New node
  +                DefaultMutableTreeNode subfolder =
  +                new DefaultMutableTreeNode("Subfolder-" + j);
  +        
  +                // Add node to parent node
  +                folder.add(subfolder);
  +        
  +                // Third level
  +                for (int k = 1; k <= 3; k++)
  +                {
  +                    // New anchor
  +                    A a = new A("http://jakarta.apache.org";);
  +                    a.setTarget("target").addElement("Document-" + k);
  +            
  +                    // New node (leaf)
  +                    DefaultMutableTreeNode document =
  +                        new DefaultMutableTreeNode(a.toString());
  +            
  +                    // Add node to parent node
  +                    subfolder.add(document);
  +                }
  +            }
  +        }
  +    
  +        // Return root node
  +        return root;
  +    }
  +    
  +    /**
  +     * Returns the specified string encoded into a format suitable for
  +     * HTML. All single-quote, double-quote, greater-than, less-than
  +     * and ampersand characters are replaced with their corresponding
  +     * HTML Character Entity codes. You can use this method to encode
  +     * the designated node names before appending this node to your
  +     * tree model. Please don't encode node names that already include
  +     * a valid tag, because they are equally converted and thus won't
  +     * be displayed by the browser.
  +     *
  +     * @param in the String to encode
  +     * @return the encoded String
  +     */
  +    public static String encodeToHtml(String in)
  +    {
  +        // New StringBuffer for output concatenation
  +        StringBuffer out = new StringBuffer();
  +    
  +        // For each character in the input string
  +        for (int i = 0; in != null && i < in.length(); i++)
  +        {
  +            // Get the current character
  +            char c = in.charAt(i);
  +        
  +            // Encode this character
  +            if (c == '\'')
  +            {
  +                out.append("&#039;");
  +            }
  +            else if (c == '\"')
  +            {
  +                out.append("&quot;");
  +            }
  +            else if (c == '<')
  +            {
  +                out.append("&lt;");
  +            }
  +            else if (c == '>')
  +            {
  +                out.append("&gt;");
  +            }
  +            else if (c == '&')
  +            {
  +                out.append("&amp;");
  +            }
  +            else
  +            {
  +                out.append(c);
  +            }
  +        }
  +    
  +        // Return encoded string
  +        return out.toString();
  +    }
  +}
  \ No newline at end of file
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to