Home » freemarker-2.3.13 » freemarker.template.utility » [javadoc | source]

    1   /*
    2    * Copyright (c) 2003 The Visigoth Software Society. All rights
    3    * reserved.
    4    *
    5    * Redistribution and use in source and binary forms, with or without
    6    * modification, are permitted provided that the following conditions
    7    * are met:
    8    *
    9    * 1. Redistributions of source code must retain the above copyright
   10    *    notice, this list of conditions and the following disclaimer.
   11    *
   12    * 2. Redistributions in binary form must reproduce the above copyright
   13    *    notice, this list of conditions and the following disclaimer in
   14    *    the documentation and/or other materials provided with the
   15    *    distribution.
   16    *
   17    * 3. The end-user documentation included with the redistribution, if
   18    *    any, must include the following acknowledgement:
   19    *       "This product includes software developed by the
   20    *        Visigoth Software Society (http://www.visigoths.org/)."
   21    *    Alternately, this acknowledgement may appear in the software itself,
   22    *    if and wherever such third-party acknowledgements normally appear.
   23    *
   24    * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
   25    *    project contributors may be used to endorse or promote products derived
   26    *    from this software without prior written permission. For written
   27    *    permission, please contact visigoths@visigoths.org.
   28    *
   29    * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
   30    *    nor may "FreeMarker" or "Visigoth" appear in their names
   31    *    without prior written permission of the Visigoth Software Society.
   32    *
   33    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   34    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   35    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   36    * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
   37    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   38    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   39    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   40    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   41    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   42    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   43    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44    * SUCH DAMAGE.
   45    * ====================================================================
   46    *
   47    * This software consists of voluntary contributions made by many
   48    * individuals on behalf of the Visigoth Software Society. For more
   49    * information on the Visigoth Software Society, please see
   50    * http://www.visigoths.org/
   51    */
   52   
   53   package freemarker.template.utility;
   54   
   55   import freemarker.template;
   56   import org.w3c.dom;
   57   import java.util;
   58   
   59   /**
   60    * A convenient wrapper class for wrapping a Node in the W3C DOM API.
   61    * @author <a href="mailto:jon@revusky.com">Jonathan Revusky</a>
   62    */
   63   
   64   public class DOMNodeModel implements TemplateHashModel {
   65   
   66       static private HashMap equivalenceTable = new HashMap();
   67       static {
   68           equivalenceTable.put("*", "children");
   69           equivalenceTable.put("@*", "attributes");
   70       }
   71   
   72       private Node node;
   73       private HashMap cache = new HashMap();
   74   
   75       public DOMNodeModel(Node node) {
   76           this.node = node;
   77       }
   78   
   79       public TemplateModel get(String key) throws TemplateModelException {
   80           TemplateModel result = null;
   81           if (equivalenceTable.containsKey(key)) {
   82               key = (String) equivalenceTable.get(key);
   83           }
   84           if (cache.containsKey(key)) {
   85               result = (TemplateModel) cache.get(key);
   86           }
   87           if (result == null) {
   88               if ("attributes".equals(key)) {
   89                   NamedNodeMap attributes = node.getAttributes();
   90                   if (attributes != null) {
   91                       SimpleHash hash = new SimpleHash();
   92                       for (int i = 0; i<attributes.getLength(); i++) {
   93                           Attr att = (Attr) attributes.item(i);
   94                           hash.put(att.getName(), att.getValue());
   95                       }
   96                       result = hash;
   97                   }
   98               }
   99               else if (key.charAt(0) == '@') {
  100                   if (node instanceof Element) {
  101                       String attValue = ((Element) node).getAttribute(key.substring(1));
  102                       result = new SimpleScalar(attValue);
  103                   }
  104                   else {
  105                       throw new TemplateModelException("Trying to get an attribute value for a non-element node");
  106                   }
  107               }
  108               else if ("is_element".equals(key)) {
  109                   result = (node instanceof Element) ?
  110                       TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
  111               }
  112               else if ("is_text".equals(key)) {
  113                   result = (node instanceof Text) ?
  114                       TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
  115               }
  116               else if ("name".equals(key)) {
  117                   result = new SimpleScalar(node.getNodeName());
  118               }
  119               else if ("children".equals(key)) {
  120                   result = new NodeListTM(node.getChildNodes());
  121               }
  122               else if ("parent".equals(key)) {
  123                   Node parent = node.getParentNode();
  124                   result = (parent == null) ? null : new DOMNodeModel(parent);
  125               }
  126               else if ("ancestorByName".equals(key)) {
  127                   result = new AncestorByName();
  128               }
  129               else if ("nextSibling".equals(key)) {
  130                   Node next = node.getNextSibling();
  131                   result = (next == null) ? null : new DOMNodeModel(next);
  132               }
  133               else if ("previousSibling".equals(key)) {
  134                   Node previous = node.getPreviousSibling();
  135                   result = (previous == null) ? null : new DOMNodeModel(previous);
  136               }
  137               else if ("nextSiblingElement".equals(key)) {
  138                   Node next = nextSiblingElement(node);
  139                   result = (next == null) ? null : new DOMNodeModel(next);
  140               }
  141               else if ("previousSiblingElement".equals(key)) {
  142                   Node previous = previousSiblingElement(node);
  143                   result = (previous == null) ? null : new DOMNodeModel(previous);
  144               }
  145               else if ("nextElement".equals(key)) {
  146                   Node next = nextElement(node);
  147                   result = (next == null) ? null : new DOMNodeModel(next);
  148               }
  149               else if ("previousElement".equals(key)) {
  150                   Node previous = previousElement(node);
  151                   result = (previous == null) ? null : new DOMNodeModel(previous);
  152               }
  153               else if ("text".equals(key)) {
  154                   result = new SimpleScalar(getText(node));
  155               }
  156               cache.put(key, result);
  157           }
  158           return result;
  159       }
  160   
  161       public boolean isEmpty() {
  162           return false;
  163       }
  164   
  165       static private String getText(Node node) {
  166           String result = "";
  167           if (node instanceof Text) {
  168               result = ((Text) node).getData();
  169           }
  170           else if (node instanceof Element) {
  171               NodeList children = node.getChildNodes();
  172               for (int i= 0; i<children.getLength(); i++) {
  173                   result += getText(children.item(i));
  174               }
  175           }
  176           return result;
  177       }
  178   
  179       static private Element nextSiblingElement(Node node) {
  180           Node next = node;
  181           while (next != null) {
  182               next = next.getNextSibling();
  183               if (next instanceof Element) {
  184                   return (Element) next;
  185               }
  186           }
  187           return null;
  188       }
  189   
  190       static private Element previousSiblingElement(Node node) {
  191           Node previous = node;
  192           while (previous != null) {
  193               previous = previous.getPreviousSibling();
  194               if (previous instanceof Element) {
  195                   return (Element) previous;
  196               }
  197           }
  198           return null;
  199       }
  200   
  201       static private Element nextElement(Node node) {
  202           if (node.hasChildNodes()) {
  203               NodeList children = node.getChildNodes();
  204               for (int i=0; i<children.getLength();i++) {
  205                   Node child = children.item(i);
  206                   if (child instanceof Element) {
  207                       return (Element) child;
  208                   }
  209               }
  210           }
  211           Element nextSiblingElement = nextSiblingElement(node);
  212           if (nextSiblingElement != null) {
  213               return nextSiblingElement;
  214           }
  215           Node parent = node.getParentNode();
  216           while (parent instanceof Element) {
  217               Element next = nextSiblingElement(parent);
  218               if (next != null) {
  219                   return next;
  220               }
  221               parent = parent.getParentNode();
  222           }
  223           return null;
  224       }
  225   
  226       static private Element previousElement(Node node) {
  227           Element result = previousSiblingElement(node);
  228           if (result != null) {
  229               return result;
  230           }
  231           Node parent = node.getParentNode();
  232           if (parent instanceof Element) {
  233               return (Element) parent;
  234           }
  235           return null;
  236       }
  237   
  238       void setParent(DOMNodeModel parent) {
  239           if (parent != null) {
  240               cache.put("parent", parent);
  241           }
  242       }
  243   
  244       String getNodeName() {
  245           return node.getNodeName();
  246       }
  247   
  248   
  249       class AncestorByName implements TemplateMethodModel {
  250           public Object exec(List arguments) throws TemplateModelException {
  251               if (arguments.size() != 1) {
  252                   throw new TemplateModelException("Expecting exactly one string argument here");
  253               }
  254               String nodeName = (String) arguments.get(0);
  255               DOMNodeModel ancestor = (DOMNodeModel) DOMNodeModel.this.get("parent");
  256               while (ancestor != null) {
  257                   if (nodeName.equals(ancestor.getNodeName())) {
  258                       return ancestor;
  259                   }
  260                   ancestor = (DOMNodeModel) ancestor.get("parent");
  261               }
  262               return null;
  263           }
  264       }
  265   
  266   
  267       class NodeListTM implements TemplateSequenceModel, TemplateMethodModel {
  268   
  269           private NodeList nodeList;
  270           private TemplateModel[] nodes;
  271   
  272           NodeListTM(NodeList nodeList) {
  273               this.nodeList = nodeList;
  274               nodes = new TemplateModel[nodeList.getLength()];
  275           }
  276   
  277           public TemplateModel get(int index) {
  278               DOMNodeModel result = (DOMNodeModel) nodes[index];
  279               if (result == null) {
  280                   result = new DOMNodeModel(nodeList.item(index));
  281                   nodes[index] = result;
  282                   result.setParent(DOMNodeModel.this);
  283               }
  284               return result;
  285           }
  286   
  287           public int size() {
  288               return nodes.length;
  289           }
  290   
  291           public Object exec(List arguments) throws TemplateModelException {
  292               if (arguments.size() != 1) {
  293                   throw new TemplateModelException("Expecting exactly one string argument here");
  294               }
  295               if (!(node instanceof Element)) {
  296                   throw new TemplateModelException("Expecting element here.");
  297               }
  298               Element elem = (Element) node;
  299               return new NodeListTM(elem.getElementsByTagName((String) arguments.get(0)));
  300           }
  301       }
  302   }
  303   

Home » freemarker-2.3.13 » freemarker.template.utility » [javadoc | source]