All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.util.html.HTMLTree Maven / Gradle / Ivy

There is a newer version: 11.1
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                                 
//                                                                             
// Filename: HTMLTree.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 1997-2002 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.util.html;

import java.util.Vector;
import java.util.Date;
import java.text.Collator;                        // @A1A
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;

import javax.servlet.http.HttpServletRequest;

import com.ibm.as400.access.Trace;
import com.ibm.as400.access.ExtendedIllegalStateException;


/**
*  The HTMLTree class represents an HTML hierarchical tree of HTML elements.
*
*  

* This example creates an HTMLTree object with five elements. * The first three elements will be added directly to the HTMLTree and the remaining two * elements will extend off one of the first three elements. * * * *

*  // Create a URLParser object.
*  URLParser urlParser = new URLParser(myHttpServletRequest.getRequestURI());
*  
*  // Create parent HTMLTreeElements.
*  HTMLTreeElement parentElement = new HTMLTreeElement();
*  parentElement.setTextUrl(new HTMLHyperlink("http://myWebPage", "My Web Page"));
*  
*  HTMLTreeElement parentElement2 = new HTMLTreeElement();
*  parentElement2.setText(new HTMLText("Parent Element 2"));
*  
*  HTMLTreeElement parentElement3 = new HTMLTreeElement();
*  parentElement3.setText(new HTMLText("Parent Element 3"));
*  
*  // Create children HTMLTreeElements.
*  HTMLTreeElement childElement1 = new HTMLTreeElement();
*  childElement1.setTextUrl(new HTMLHyperlink("http://anotherWebPage", "Another Web Page"));
*  parentElement.addElement(childElement1);
*  
*  // Create a child of the first Child Element.
*  HTMLTreeElement subChildElement1 = new HTMLTreeElement();
*  subChildElement1.setText(new HTMLHyperlink("http://myHomePage", "Home"));
*  
*  // Add the sub-child to the parent child element.
*  childElement1.addElement(subChildElement1);
*  
*  // Set the URL link for the Expand/Collapsed Icon.
*  ServletHyperlink iconUrl = new ServletHyperlink(urlParser.getURI());
*  iconUrl.setHttpServletResponse(resp);
*  parentElement.setIconUrl(iconUrl);
*  parentElement2.setIconUrl(iconUrl);
*  parentElement3.setIconUrl(iconUrl);
*  
*  // Add the parent elements to the tree.
*  tree.addElement(parentElement);
*  tree.addElement(parentElement2);
*  tree.addElement(parentElement3);
*  
* *

* When the HTMLTree is first viewed in a browser, none of the elements in the tree will be * expanded, so the tree will look like this: * *

* * * * * * * * * * * * *
* + * * My Web Page
* * Parent Element 2 *
* * Parent Element 3 *
* *

* When the elements in the HTMLTree are expanded by traversing the hierarchy, the tree will look like: * *

* * * * * * * * * * * * * *
* - * * My Web Page
  * * * * * * *
* - * * Another Web Page
  * * * * * *
* * Home *
*
*
* * Parent Element 2 *
* * Parent Element 3 *
* *

* HTMLTree objects generate the following events: *

    *
  • ElementEvent - The events fired are: *
      *
    • elementAdded *
    • elementRemoved *
    *
  • PropertyChangeEvent *
* * @see com.ibm.as400.util.html.HTMLTreeElement * @see com.ibm.as400.util.html.URLParser **/ public class HTMLTree implements HTMLTagElement, java.io.Serializable { private static final String copyright = "Copyright (C) 1997-2002 International Business Machines Corporation and others."; static final long serialVersionUID = 4170861562301214202L; private HTMLVector branches_; //@P2C private HttpServletRequest request_; private boolean sort_ = true; // @A1A transient private Collator collator_; // @A1A @B2C transient private PropertyChangeSupport changes_; //@P2C transient private Vector elementListeners_; // The list of element listeners @P2C /** * Constructs a default HTMLTree object. **/ public HTMLTree() { super(); // @B2A // If the locale is Korean, then this throws // an ArrayIndexOutOfBoundsException. This is // a bug in the JDK. The workarond in that case // is just to use String.compareTo(). try // @B2A { collator_ = Collator.getInstance (); // @B2A collator_.setStrength (Collator.PRIMARY); // @B2A } catch (Exception e) // @B2A { collator_ = null; // @B2A } branches_ = new HTMLVector(); //@P2C } /** * Constructs an HTMLTree object with the specified HttpServletRequest. * The request is the mechanism used to provide continuity while expanding * and collapsing the tree. * @param request **/ public HTMLTree(HttpServletRequest request) { this(); setHttpServletRequest(request); } /** * Adds an HTMLTreeElement to the tree. * * @param element The HTMLTreeElement. **/ public void addElement(HTMLTreeElement element) { if (element == null) throw new NullPointerException("element"); //@B3D branches_.addElement(element); if (elementListeners_ != null) fireElementEvent(ElementEvent.ELEMENT_ADDED); //@P2C } /** * Adds an addElementListener. * The specified addElementListeners elementAdded method will * be called each time a RadioFormInput is added to the group. * The addElementListener object is added to a list of addElementListeners * managed by this RadioFormInputGroup. It can be removed with removeElementListener. * * @see #removeElementListener * * @param listener The ElementListener. **/ public void addElementListener(ElementListener listener) { if (listener == null) throw new NullPointerException ("listener"); if (elementListeners_ == null) elementListeners_ = new Vector(); //@P2A elementListeners_.addElement(listener); } /** * Adds a PropertyChangeListener. The specified * PropertyChangeListener's propertyChange * method is called each time the value of any * bound property is changed. * * @see #removePropertyChangeListener * @param listener The PropertyChangeListener. **/ public void addPropertyChangeListener(PropertyChangeListener listener) { if (listener == null) throw new NullPointerException("listener"); if (changes_ == null) changes_ = new PropertyChangeSupport(this); //@P2A changes_.addPropertyChangeListener(listener); } /** * Deserializes and initializes transient data. **/ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { // @B2A // If the locale is Korean, then this throws // an ArrayIndexOutOfBoundsException. This is // a bug in the JDK. The workarond in that case // is just to use String.compareTo(). try // @B2A { collator_ = Collator.getInstance (); // @B2A collator_.setStrength (Collator.PRIMARY); // @B2A } catch (Exception e) // @B2A { collator_ = null; // @B2A } in.defaultReadObject(); //@P2D changes_ = new PropertyChangeSupport(this); //@P2D elementListeners = new Vector(); } /** * Removes an HTMLTreeElement from the tree. * * @param element The HTMLTreeElement. **/ public void removeElement(HTMLTreeElement element) { if (element == null) throw new NullPointerException("element"); //@B3D if (branches_.removeElement(element) && elementListeners_ != null) //@P2C fireElementEvent(ElementEvent.ELEMENT_REMOVED); } /** * Removes this ElementListener from the internal list. * If the ElementListener is not on the list, nothing is done. * * @see #addElementListener * * @param listener The ElementListener. **/ public void removeElementListener(ElementListener listener) { if (listener == null) throw new NullPointerException ("listener"); if (elementListeners_ != null) elementListeners_.removeElement(listener); //@P2C } /** * Removes the PropertyChangeListener from the internal list. * If the PropertyChangeListener is not on the list, nothing is done. * * @see #addPropertyChangeListener * @param listener The PropertyChangeListener. **/ public void removePropertyChangeListener(PropertyChangeListener listener) { if (listener == null) throw new NullPointerException("listener"); if (changes_ != null) changes_.removePropertyChangeListener(listener); //@P2C } /** * Fires the element event. **/ private void fireElementEvent(int evt) { Vector targets; targets = (Vector) elementListeners_.clone(); ElementEvent elementEvt = new ElementEvent(this, evt); for (int i = 0; i < targets.size(); i++) { ElementListener target = (ElementListener)targets.elementAt(i); if (evt == ElementEvent.ELEMENT_ADDED) target.elementAdded(elementEvt); else if (evt == ElementEvent.ELEMENT_REMOVED) target.elementRemoved(elementEvt); } } /** * Returns the HttpServletRequest. * * @return The request. **/ public HttpServletRequest getHttpServletRequest() { return request_; } /** * Returns the Collator. * * @return The collator. **/ public Collator getCollator() // @B2A { return collator_; } /** * Returns a comment tag. * This method should not be called. There is no XSL-FO support for this class. * @return The comment tag. **/ public String getFOTag() //@C1A { Trace.log(Trace.ERROR, "Attempting to getFOTag() for an object that doesn't support it."); return ""; } /** * Returns the HTMLTree tag. * * @return The tag. **/ public String getTag() { //@B3D if (request_ == null) throw new ExtendedIllegalStateException("request", ExtendedIllegalStateException.PROPERTY_NOT_SET ); // Get the hashcode parameter from the HTTP request. String hcStr = request_.getParameter("hashcode"); // @B1C StringBuffer buf1 = new StringBuffer("\n"); if (sort_) sort(collator_, branches_); // @A1A @B2C @P2C int size = branches_.getCount(); //@P2A Object[] data = branches_.getData(); //@P2A for (int i=0; i\n"); return buf1.toString(); } /** * Sets the collator. The collator allows the tree to perform * locale-sensitive String comparisons when sorting the tree elements. * * @param collator The Collator. **/ public void setCollator(Collator collator) // @B2A { if (collator == null) throw new NullPointerException("collator"); Collator old = collator_; collator_ = collator; if (changes_ != null) changes_.firePropertyChange("collator", old, collator_); //@P2C } /** * Sets the Http servlet request. The request is the mechanism * used to provide continuity while expanding and collapsing the tree. * * @param request The Http servlet request. **/ public void setHttpServletRequest(HttpServletRequest request) { if (request == null) throw new NullPointerException("request"); HttpServletRequest old = request_; request_ = request; if (changes_ != null) changes_.firePropertyChange("request", old, request_); //@P2C } /** * Sorts the elements within the HTMLTree. * * @param sort true if the elements are sorted; false otherwise. * The default is true. **/ public void sort(boolean sort) // @A1A { sort_ = sort; } /** * Sorts a vector of objects. * * @param collator The Collator, or null if the default Collator should be used. * @param list The objects. * * @return The sorted Vector. **/ public static Vector sort (Collator collator, Vector list) // @A1A @B2C @B4C @P2C { heapSort(collator, list); // @B2A return list; } /** * Method used to perform a heap sort, * which is faster than a quick sort and * a bubble sort. * * @param collator The collator. * @param sortlist The list to sort. **/ private static void heapSort(Collator collator, Vector sortlist) // @B2A { int numberOfEntries = sortlist.size(); int i; Object temp = null; if (numberOfEntries > 0) { // convert table list map into a heap for (i = (numberOfEntries/2); i != 0; i--) { adjustList(collator, sortlist,i,numberOfEntries); } // sort table list for (i = (numberOfEntries - 1); i != 0; i--) { // swap first and last entries in heap to get largest remaining // table name correctly placed temp = sortlist.elementAt(i); sortlist.setElementAt(sortlist.elementAt(0),i); sortlist.setElementAt(temp,0); // create new heap with the remaining nodes adjustList(collator, sortlist,1,i); } } } /** * Utility routine used by heap sort **/ private static void adjustList(Collator collator, Vector sortlist, int rootIndex, int maxIndex) // @B2A { Object rootItem = sortlist.elementAt(rootIndex-1); int j = rootIndex * 2; Object itemAtJ = null; Object itemAtJLess1 = null; boolean done = false; // traverse tree while ((j <= maxIndex) && (done == false)) { itemAtJLess1 = sortlist.elementAt(j-1); if (j < maxIndex) { itemAtJ = sortlist.elementAt(j); // find greater table name of left and right child if (sortCompare(collator, itemAtJLess1, itemAtJ) < 0) { j++; itemAtJLess1 = itemAtJ; } } // if root table name is greater than max child if (sortCompare(collator, rootItem, itemAtJLess1) >= 0) done = true; // root table name less than max child else { // move max child up tree sortlist.setElementAt(sortlist.elementAt(j-1),(j/2)-1); // move to next level j = j * 2; } } // place original root in proper place sortlist.setElementAt(rootItem,(j/2)-1); } /** * Compares two objects for the sort. * * @param objectI The ith object. * @param objectJ The jth object. * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater * than the second. **/ private static int sortCompare (Collator collator, Object objectI, Object objectJ) // @A1A { Object valueI; Object valueJ; // When the object is a HTMLTreeElement or FileTreeElement the // sort must be done against the name or viewable text // of the element otherwise nothing will be sorted properly. if (objectI instanceof FileTreeElement) { // @B2C valueI = ((FileTreeElement)objectI).getFile().getName(); valueJ = ((FileTreeElement)objectJ).getFile().getName(); } else if (objectI instanceof HTMLTreeElement) // @B2C { valueI = ((HTMLTreeElement)objectI).getText(); valueJ = ((HTMLTreeElement)objectJ).getText(); } else { valueI = objectI.toString(); valueJ = objectJ.toString(); } // Check for nulls. if (valueI == null) valueI = ""; if (valueJ == null) valueJ = ""; int comparison = 0; // If they are equal, then use the next column. if (collator != null) // Otherwise, do the comparison using this column. comparison = collator.compare (valueI.toString(), valueJ.toString()); // @B2C else comparison = valueI.toString().compareTo(valueJ.toString()); // @B2C // Return the value. return comparison; } }