View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.xml;
17  
18  import org.apache.commons.jelly.JellyTagException;
19  import org.apache.commons.jelly.MissingAttributeException;
20  import org.apache.commons.jelly.XMLOutput;
21  import org.apache.commons.jelly.xpath.XPathComparator;
22  import org.apache.commons.jelly.xpath.XPathTagSupport;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  import org.jaxen.XPath;
28  import org.jaxen.JaxenException;
29  
30  import java.util.ArrayList;
31  import java.util.List;
32  import java.util.Collections;
33  
34  /*** A tag which defines a variable from an XPath expression.
35    * This function creates a variable of type {@link List} or {@link org.dom4j.Node}
36    * (for example {@link org.dom4j.Element} or {@link org.dom4j.Attribute}).
37    * Thus, the variable created from xml:set can be
38    * used from the other xml library functions.
39    *
40    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
41    * @version $Revision: 1.11 $
42    */
43  public class SetTag extends XPathTagSupport {
44  
45      /*** The Log to which logging calls will be made. */
46      private Log log = LogFactory.getLog(SetTag.class);
47  
48      /*** The variable name to export. */
49      private String var;
50  
51      /*** The XPath expression to evaluate. */
52      private XPath select;
53  
54      /*** Xpath comparator for sorting */
55      private XPathComparator xpCmp = null;
56  
57      private Boolean single=null;
58  
59      public SetTag() {
60  
61      }
62  
63      // Tag interface
64      //-------------------------------------------------------------------------
65      public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException {
66          if (var == null) {
67              throw new MissingAttributeException( "var" );
68          }
69          if (select == null) {
70              throw new MissingAttributeException( "select" );
71          }
72  
73          Object xpathContext = getXPathContext();
74          Object value = null;
75          try {
76              if(single!=null && single.booleanValue()==true) {
77                  value = select.selectSingleNode(xpathContext);
78              } else {
79                  value = select.evaluate(xpathContext);
80              }
81          }
82          catch (JaxenException e) {
83              throw new JellyTagException(e);
84          }
85  
86          if (value instanceof List) {
87              // sort the list if xpCmp is set.
88              if (xpCmp != null && (xpCmp.getXpath() != null)) {
89                  Collections.sort((List)value, xpCmp);
90              }
91          }
92          if (single!=null) {
93              if (single.booleanValue()==true) {
94                  if(value instanceof List) {
95                      List l = (List) value;
96                      if (l.size()==0)
97                          value=null;
98                      else
99                          value=l.get(0);
100                 }
101             } else { // single == false
102                 if(! (value instanceof List) ) {
103                     List l = null;
104                     if (value==null) {
105                         l = new ArrayList(0);
106                     } else {
107                         l = new ArrayList(1);
108                         l.add(value);
109                     }
110                     value = l;
111                 }
112             }
113         }
114 
115         //log.info( "Evaluated xpath: " + select + " as: " + value + " of type: " + value.getClass().getName() );
116 
117         context.setVariable(var, value);
118     }
119 
120     // Properties
121     //-------------------------------------------------------------------------
122 
123     /*** Sets the variable name to define for this expression
124      */
125     public void setVar(String var) {
126         this.var = var;
127     }
128 
129     /*** Sets the XPath expression to evaluate. */
130     public void setSelect(XPath select) {
131         this.select = select;
132     }
133 
134     /*** If set to true will only take the first element matching.
135         If set to false, guarantees that a list is returned.
136         It then guarantees that the result is of type
137         {@link org.dom4j.Node} thereby making sure that, for example,
138         when an element is selected, one can directly call such methods
139         as setAttribute.
140         */
141     public void setSingle(boolean single) {
142         this.single = new Boolean(single);
143     }
144 
145 
146     /*** Sets the xpath expression to use to sort selected nodes.
147      *  Ignored if single is true.
148      */
149     public void setSort(XPath sortXPath) throws JaxenException {
150         if (xpCmp == null) xpCmp = new XPathComparator();
151         xpCmp.setXpath(sortXPath);
152     }
153 
154     /***
155      * Set whether to sort ascending or descending.
156      */
157     public void setDescending(boolean descending) {
158         if (xpCmp == null) xpCmp = new XPathComparator();
159         xpCmp.setDescending(descending);
160     }
161 }