1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
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 {
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
116
117 context.setVariable(var, value);
118 }
119
120
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 }