alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  
"); } } else { TreeLeaf leaf = (TreeLeaf)treeObject; buf.append( renderLeafHTML(leaf) ); } } buf.append("\n</TABLE>\n"); return buf.toString(); } /** * Renders the specified tree node as HTML. */ private final String renderNodeHTML(TreeNode node) { StringBuffer buf = new StringBuffer(); boolean visible = isVisible(node); buf.append( "<tr>" ); return buf.toString(); } /** * Renders the specified tree leaf as HTML. */ private final String renderLeafHTML( TreeLeaf leaf ) { StringBuffer buf = new StringBuffer(); buf.append( "<tr>" ); return buf.toString(); } /** * Accepts a comma separated list of tokens and returns them as a string array. */ private String[] csvToArray(String csv) { StringTokenizer st = new StringTokenizer(csv,","); String[] buf = new String[st.countTokens()]; int i = 0; while(st.hasMoreTokens()) buf[i++] = st.nextToken(); return buf; } public String adjustScrollPosition() { // return "<SCRIPT> window.location.href=\"#A\"; if(window.scrollTo) scrollTo(0,(document.body ? document.body.scrollTop : pageYOffset) - 20); "; return "<SCRIPT> window.location.href=\"#A\"; window.scroll(0, -20); "; } }

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/**
 * CSTreeBean.java
 * Version 0.3, September 12, 2000
 *
 * Copyright (C) 2000 CoolServlets.com. All rights reserved.
 *
 * Derived from CoolServlets tree classes. Maintainer: Kevin Sangeelee
 *
 * ===================================================================
 * The Apache Software License, Version 1.1
 *
 * 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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by
 *        CoolServlets.com (http://www.coolservlets.com)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Jive" and "CoolServlets.com" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please
 *    contact webmaster@coolservlets.com.
 *
 * 5. Products derived from this software may not be called "Jive",
 *    nor may "Jive" appear in their name, without prior written
 *    permission of CoolServlets.com.
 *
 * THIS SOFTWARE IS PROVIDED ``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 COOLSERVLETS.COM 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 CoolServlets.com. For more information
 * on CoolServlets.com, please see <http://www.coolservlets.com>.
 */
package com.coolservlets.beans;

import java.sql.*;
import java.util.*;
import javax.servlet.http.*;
import com.coolservlets.beans.tree.*;

/**
 * A CSTreeBean is a server-side JSP JavaBean that generates trees populated from a JDBC
 * data source, and renders the trees as HTML. State information is maintained using URI
 * parameters.
 */
 
public class CSTreeBean {

	private static Hashtable trees = new Hashtable();

	private Hashtable openNodes = new Hashtable();	// holds an easy-lookup of open nodes while rendering HTML

	private String jdbcDriver;
	private String jdbcURL;
	private String jdbcUser;
	private String jdbcPassword;

	private String treeName;						// unique name of this tree
	private String tableName;						// name of the (denormalised) table or view
	private String labelCols;						// comma separated list of columns that hold labels
	private String urlCols;							// comma separated list of corresponding urls
	private String whereClause = "";

	private String treePage;						// Which page to send tree URL links to
	private String leafPage;						// Which page to send tree leaf links to
	private String leafTarget;						// Which frame to send non-tree URL links to

	private String openImage="fldo.gif";			// image for open nodes
	private String closedImage="fldc.gif";			// image for closed nodes
	private String leafImage="rgn.gif";				// image for leaf nodes

	private String treeStyle;						// Text style of the table

	private int open = 0;			// Passed by URL to this bean stating which node to open (or close)
	private int absopen;			// what - no abs()??
	private String oldopen = "";	// Automatically maintained URL parameter listing open nodes
	private boolean reload = false;

	// Getter and Setter methods
	public String	getJdbcDriver() { return this.jdbcDriver; }
	public void		setJdbcDriver(String str) { this.jdbcDriver = str; }
	public String	getJdbcURL() { return this.jdbcURL; }
	public void		setJdbcURL(String str) { this.jdbcURL = str; }
	public String	getJdbcUser() { return this.jdbcUser; }
	public void		setJdbcUser(String str) { this.jdbcUser = str; }
	public String	getJdbcPassword() { return this.jdbcPassword; }
	public void		setJdbcPassword(String str) { this.jdbcPassword = str; }

	public String	getLabelCols() { return this.labelCols; }
	public void		setLabelCols(String str) { this.labelCols = str; }
	public String	getUrlCols() { return this.urlCols; }
	public void		setUrlCols(String str) { this.urlCols = str; }
	public String	getTreeName() { return this.treeName; }
	public void		setTreeName(String str) { this.treeName = str; }
	public String	getTableName() { return this.tableName; }
	public void		setTableName(String str) { this.tableName = str; }
	public String	getWhereClause() { return this.whereClause; }
	public void		setWhereClause(String str) { this.whereClause = str; }

	//public String	get() { return this.; }
	//public void	set(String str) { this. = str; }

	public String getTreePage() { return treePage; }
	public void setTreePage(String treePage) { this.treePage = treePage; }

	public String getLeafPage() { return leafPage; }
	public void setLeafPage(String leafPage) { this.leafPage = leafPage; }
	public String getLeafTarget() { return leafTarget; }
	public void setLeafTarget(String leafTarget) { this.leafTarget = leafTarget; }

	public String getTreeStyle() { return treeStyle; }
	public void setTreeStyle(String treeStyle) { this.treeStyle = treeStyle; }

	public int	getOpen() { return open; }
	public void setOpen(int open) { this.open = open; absopen = open < 0 ? -open : open; }
	public String getOldopen() { return oldopen; }
	public void setOldopen(String oldopen) { this.oldopen = oldopen; }
	
	public boolean	getReload() { return reload; }
	public void setReload(boolean reload) { this.reload = reload; }

	public void		setOpenImage(String str) { this.openImage = str; }
	public void		setClosedImage(String str) { this.closedImage = str; }
	public void		setLeafImage(String str) { this.leafImage = str; }

	// Now on to the real stuff...

	/**
	 * Populates the tree specified in the bean parameter 'treeName', or the default tree
	 * if none was specified. The trees are held statically in a Hashtable, keyed on the tree
	 * name.
	 * 
	 * A tree is populated from a denormalised table or a view using JDBC. Ordinarily, this operation
	 * happens only once when the tree is first accessed.
	 *
	 * This method should probably be reorganised to lend itself more to populating from sources other
	 * than JDBC.
	 */

	public synchronized boolean populateJdbc() {

		boolean sqlerror = false;

		/** Try to get the named tree from the Hashtable. If no name is provided, use 'default'.
			If a tree matches, then it must already be populated.
		*/
		if(treeName == null || treeName.length() == 0) {
			treeName = "default";
		}
		if(trees.get(treeName) != null && reload == false) {
			return true;		// already populated
		}
		System.out.println("Populating tree from the database.");

		// Get a database connection

		Connection con = null;
		try {
			Class.forName(jdbcDriver);
			con = DriverManager.getConnection (jdbcURL, jdbcUser, jdbcPassword);
		}
		catch(ClassNotFoundException e) {
			System.out.println(e.toString());
			return false;
		}
		catch(SQLException e) {
			System.out.println(e.toString());
			return false;
		}

		String[] labelColumns = csvToArray(labelCols);
		String[] urlColumns = csvToArray(urlCols);

		String[] labels = new String[30];	// hardwired maximum depth of 30 levels (!!)
		String[] urls = new String[30];	// hardwired maximum depth of 30 levels (!!)
		TreeNode tn[] = new TreeNode[30];
		int nodeID = 1;

		Tree root;
		root = new Tree("root");

		TreeNode node = null;
		
		try {
			Statement stmt = con.createStatement();
			StringBuffer sql = new StringBuffer(300);

			sql.append("select distinct ").append(labelCols).append(",").append(urlCols);
			sql.append(" from ").append(tableName);
			sql.append(" ").append(whereClause).append(" order by ").append(labelCols);

			ResultSet rs = stmt.executeQuery( sql.toString() );
			int i,j = 0;

			while(rs.next()) {	// iterate through the denormalised view

				/** This reading of a 'line' has been decoupled from the main populating logic below
				 *  so that different types of data source can be added.
				 */
				for(i=0; i < labelColumns.length; i++) {	// for each column
					if(((labels[i] = rs.getString(labelColumns[i]))) == null || labels[i].length() == 0)
						break;
					if((urls[i] = rs.getString(urlColumns[i])) != null && urls[i].length() == 0)
						urls[i] = null;	// force empty url columns to null for easy testing later...
				}

				for(j=0; j < i-1; j++) {

					if(tn[j] == null || !labels[j].equals(tn[j].getName())) {	// then this is the first or a new item
						tn[j] = new TreeNode(nodeID++, labels[j], urls[j]);
						if(j > 0)
							tn[j-1].addChild(tn[j]);
						else
							root.addChild(tn[j]);
						continue;
					}
				}
				if(j > 0)
					tn[j-1].addChild( new TreeLeaf( labels[j], urls[j]) );
				else
					root.addChild(new TreeLeaf(labels[j],urls[j]));
			}

			trees.put(treeName, root);	// Store the tree in the static Hashtable

		} catch(SQLException e) {
			System.out.println(e.toString());
			sqlerror = true;
		}
	
		try {
			con.close();
		}
		catch(SQLException ignored) {}
		return !sqlerror;
	}

	/**
	 * This method is just a call to the method below with a null argument, meaning that the tree
	 * shouldn't get it's state from the session.
	 */
	public final String renderHTML() {
		return renderHTML((HttpServletRequest)null);
	}

	/**
	 * This method first of all builds a Hashtable of open nodes from the request parameter 
	 * for easy lookup later. It then submits the root node of the tree named in the bean 
	 * parameter 'treeName' (or the default tree) for rendering as HTML. If a HttpServletRequest
	 * is supplied, the method will try to obtain '<treeName>.oldopen' from the session.
	 */

	public final String renderHTML( HttpServletRequest req ) {

		if(populateJdbc() == false)	{		// ensures the tree is populated
			return "<p>The CDTreeBean has not been successfully initialised. Check the server's stdout for details.

"; } // Try to obtain 'oldopen' from the session if a request object was passed if(req != null) { HttpSession s = req.getSession(false); String tmp = s != null ? (String)s.getAttribute(treeName + ".oldopen") : null; if(tmp != null && tmp.length() > 0) oldopen = tmp; } // Make a hash table of the currently open nodes (from the URL parameter) StringTokenizer st = new StringTokenizer(oldopen, ":"); String token; while(st.hasMoreElements()) { try { token = st.nextToken(); openNodes.put(Integer.valueOf(token), token); // strb.append(token).append(":"); } catch(NumberFormatException e) { System.out.println("Warning: TreeBean was passed dodgy parameters!"); } } // now add the requested node to the open list (if not a close-request) if(open >= 0) { openNodes.put(new Integer(open), String.valueOf(open)); // strb.append(open); } else { openNodes.remove(new Integer(-open)); } StringBuffer strb = new StringBuffer(); Enumeration on = openNodes.elements(); while(on.hasMoreElements()) { strb.append(on.nextElement()).append(":"); } this.oldopen = strb.toString(); // Try to write 'oldopen' to the session if a request object was passed if(req != null) { HttpSession s = req.getSession(false); if(s != null) s.setAttribute(treeName + ".oldopen", oldopen); } StringBuffer html = new StringBuffer(renderHTML((Tree)trees.get(treeName))); return html.toString(); } private boolean isVisible(TreeNode node) { if(openNodes.containsKey(new Integer(node.getId()))) return true; return false; } /** * Renders the specified tree as HTML by iterating over all it's children. Will call itself * recursively for any visible node children. */ private final String renderHTML(Tree tree) { StringBuffer buf = new StringBuffer(); buf.append("\n<TABLE border=\"0\""); if(treeStyle != null && treeStyle.length() > 0) buf.append(" class=\"").append(treeStyle).append("\""); buf.append(">\n"); for( int i=0; i < tree.size(); i++ ) { TreeObject treeObject = tree.getChild(i); if( treeObject.getType() == Tree.NODE ) { TreeNode node = (TreeNode)treeObject; buf.append( renderNodeHTML(node) ); if( isVisible(node) ) { buf.append("<tr>
 ").append( renderHTML( node.getChildren() ) ).append("
" ); String link = node.getLink(); if( link != null ) { buf.append( "<a href='"); if(leafPage != null && leafPage.length() > 0) // if a leafPage is specified, then prepend to the link buf.append(leafPage); buf.append(link).append("' "); if(leafTarget != null && leafTarget.length() > 0) buf.append("target='").append(leafTarget).append("'"); buf.append(">" ).append( node.getName() ).append( "</a>" ); } else { buf.append( node.getName() ); } buf.append( "</td>
").append("") .append("</td>
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.