Save This Page
Home » dom4j-1.6.1 » org.dom4j.io » [javadoc | source]
    1   /*
    2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    3    *
    4    * This software is open source.
    5    * See the bottom of this file for the licence.
    6    */
    7   
    8   package org.dom4j.io;
    9   
   10   import java.util.ArrayList;
   11   import java.util.HashMap;
   12   
   13   import org.dom4j.Element;
   14   import org.dom4j.ElementHandler;
   15   import org.dom4j.ElementPath;
   16   
   17   /**
   18    * <p>
   19    * <code>DispatchHandler</code> implements the <code>ElementHandler</code>
   20    * interface and provides a means to register multiple
   21    * <code>ElementHandler</code> instances to be used by an event based
   22    * processor. This is a special <code>ElementHandler</code> in that it's
   23    * <b>onStart </b> and <b>onEnd </b> implementation methods are called for every
   24    * element encountered during the parse. It then delegates to other
   25    * <code>ElementHandler</code> instances registered with it to process the
   26    * elements encountered.
   27    * </p>
   28    * 
   29    * @author <a href="mailto:dwhite@equipecom.com">Dave White </a>
   30    * @version $Revision: 1.11 $
   31    */
   32   class DispatchHandler implements ElementHandler {
   33       /** Whether the parser is at the root element or not */
   34       private boolean atRoot;
   35   
   36       /** The current path in the XML tree (i.e. /a/b/c) */
   37       private String path;
   38   
   39       /** maintains a stack of previously encountered paths */
   40       private ArrayList pathStack;
   41   
   42       /** maintains a stack of previously encountered handlers */
   43       private ArrayList handlerStack;
   44   
   45       /**
   46        * <code>HashMap</code> maintains the mapping between element paths and
   47        * handlers
   48        */
   49       private HashMap handlers;
   50   
   51       /**
   52        * <code>ElementHandler</code> to use by default for element paths with no
   53        * handlers registered
   54        */
   55       private ElementHandler defaultHandler;
   56   
   57       public DispatchHandler() {
   58           atRoot = true;
   59           path = "/";
   60           pathStack = new ArrayList();
   61           handlerStack = new ArrayList();
   62           handlers = new HashMap();
   63       }
   64   
   65       /**
   66        * Adds the <code>ElementHandler</code> to be called when the specified
   67        * path is encounted.
   68        * 
   69        * @param handlerPath
   70        *            is the path to be handled
   71        * @param handler
   72        *            is the <code>ElementHandler</code> to be called by the event
   73        *            based processor.
   74        */
   75       public void addHandler(String handlerPath, ElementHandler handler) {
   76           handlers.put(handlerPath, handler);
   77       }
   78   
   79       /**
   80        * Removes the <code>ElementHandler</code> from the event based processor,
   81        * for the specified path.
   82        * 
   83        * @param handlerPath
   84        *            is the path to remove the <code>ElementHandler</code> for.
   85        * 
   86        * @return DOCUMENT ME!
   87        */
   88       public ElementHandler removeHandler(String handlerPath) {
   89           return (ElementHandler) handlers.remove(handlerPath);
   90       }
   91   
   92       /**
   93        * DOCUMENT ME!
   94        * 
   95        * @param handlerPath
   96        *            DOCUMENT ME!
   97        * 
   98        * @return true when an <code>ElementHandler</code> is registered for the
   99        *         specified path.
  100        */
  101       public boolean containsHandler(String handlerPath) {
  102           return handlers.containsKey(handlerPath);
  103       }
  104   
  105       /**
  106        * Get the registered {@link ElementHandler}for the specified path.
  107        * 
  108        * @param handlerPath
  109        *            XML path to get the handler for
  110        * 
  111        * @return the registered handler
  112        */
  113       public ElementHandler getHandler(String handlerPath) {
  114           return (ElementHandler) handlers.get(handlerPath);
  115       }
  116   
  117       /**
  118        * Returns the number of {@link ElementHandler}objects that are waiting for
  119        * their elements closing tag.
  120        * 
  121        * @return number of active handlers
  122        */
  123       public int getActiveHandlerCount() {
  124           return handlerStack.size();
  125       }
  126   
  127       /**
  128        * When multiple <code>ElementHandler</code> instances have been
  129        * registered, this will set a default <code>ElementHandler</code> to be
  130        * called for any path which does <b>NOT </b> have a handler registered.
  131        * 
  132        * @param handler
  133        *            is the <code>ElementHandler</code> to be called by the event
  134        *            based processor.
  135        */
  136       public void setDefaultHandler(ElementHandler handler) {
  137           defaultHandler = handler;
  138       }
  139   
  140       /**
  141        * Used to remove all the Element Handlers and return things back to the way
  142        * they were when object was created.
  143        */
  144       public void resetHandlers() {
  145           atRoot = true;
  146           path = "/";
  147           pathStack.clear();
  148           handlerStack.clear();
  149           handlers.clear();
  150           defaultHandler = null;
  151       }
  152   
  153       /**
  154        * DOCUMENT ME!
  155        * 
  156        * @return the current path for the parse
  157        */
  158       public String getPath() {
  159           return path;
  160       }
  161   
  162       // The following methods implement the ElementHandler interface
  163       public void onStart(ElementPath elementPath) {
  164           Element element = elementPath.getCurrent();
  165   
  166           // Save the location of the last (i.e. parent) path
  167           pathStack.add(path);
  168   
  169           // Calculate the new path
  170           if (atRoot) {
  171               path = path + element.getName();
  172               atRoot = false;
  173           } else {
  174               path = path + "/" + element.getName();
  175           }
  176   
  177           if ((handlers != null) && (handlers.containsKey(path))) {
  178               // The current node has a handler associated with it.
  179               // Find the handler and save it on the handler stack.
  180               ElementHandler handler = (ElementHandler) handlers.get(path);
  181               handlerStack.add(handler);
  182   
  183               // Call the handlers onStart method.
  184               handler.onStart(elementPath);
  185           } else {
  186               // No handler is associated with this node, so use the
  187               // defaultHandler it it exists.
  188               if (handlerStack.isEmpty() && (defaultHandler != null)) {
  189                   defaultHandler.onStart(elementPath);
  190               }
  191           }
  192       }
  193   
  194       public void onEnd(ElementPath elementPath) {
  195           if ((handlers != null) && (handlers.containsKey(path))) {
  196               // This node has a handler associated with it.
  197               // Find the handler and pop it from the handler stack.
  198               ElementHandler handler = (ElementHandler) handlers.get(path);
  199               handlerStack.remove(handlerStack.size() - 1);
  200   
  201               // Call the handlers onEnd method
  202               handler.onEnd(elementPath);
  203           } else {
  204               // No handler is associated with this node, so use the
  205               // defaultHandler it it exists.
  206               if (handlerStack.isEmpty() && (defaultHandler != null)) {
  207                   defaultHandler.onEnd(elementPath);
  208               }
  209           }
  210   
  211           // Set path back to its parent
  212           path = (String) pathStack.remove(pathStack.size() - 1);
  213   
  214           if (pathStack.size() == 0) {
  215               atRoot = true;
  216           }
  217       }
  218   }
  219   
  220   /*
  221    * Redistribution and use of this software and associated documentation
  222    * ("Software"), with or without modification, are permitted provided that the
  223    * following conditions are met:
  224    * 
  225    * 1. Redistributions of source code must retain copyright statements and
  226    * notices. Redistributions must also contain a copy of this document.
  227    * 
  228    * 2. Redistributions in binary form must reproduce the above copyright notice,
  229    * this list of conditions and the following disclaimer in the documentation
  230    * and/or other materials provided with the distribution.
  231    * 
  232    * 3. The name "DOM4J" must not be used to endorse or promote products derived
  233    * from this Software without prior written permission of MetaStuff, Ltd. For
  234    * written permission, please contact dom4j-info@metastuff.com.
  235    * 
  236    * 4. Products derived from this Software may not be called "DOM4J" nor may
  237    * "DOM4J" appear in their names without prior written permission of MetaStuff,
  238    * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
  239    * 
  240    * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
  241    * 
  242    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
  243    * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  244    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  245    * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
  246    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  247    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  248    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  249    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  250    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  251    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  252    * POSSIBILITY OF SUCH DAMAGE.
  253    * 
  254    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
  255    */

Save This Page
Home » dom4j-1.6.1 » org.dom4j.io » [javadoc | source]