1 7 8 package org.dom4j.xpath; 9 10 import java.io.Serializable ; 11 import java.util.Collections ; 12 import java.util.Comparator ; 13 import java.util.HashMap ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 import org.dom4j.InvalidXPathException; 20 import org.dom4j.Node; 21 import org.dom4j.NodeFilter; 22 import org.dom4j.XPathException; 23 24 import org.jaxen.FunctionContext; 25 import org.jaxen.JaxenException; 26 import org.jaxen.NamespaceContext; 27 import org.jaxen.SimpleNamespaceContext; 28 import org.jaxen.VariableContext; 29 import org.jaxen.XPath; 30 import org.jaxen.dom4j.Dom4jXPath; 31 32 41 public class DefaultXPath implements org.dom4j.XPath, NodeFilter, Serializable { 42 private String text; 43 44 private XPath xpath; 45 46 private NamespaceContext namespaceContext; 47 48 57 public DefaultXPath(String text) throws InvalidXPathException { 58 this.text = text; 59 this.xpath = parse(text); 60 } 61 62 public String toString() { 63 return "[XPath: " + xpath + "]"; 64 } 65 66 68 73 public String getText() { 74 return text; 75 } 76 77 public FunctionContext getFunctionContext() { 78 return xpath.getFunctionContext(); 79 } 80 81 public void setFunctionContext(FunctionContext functionContext) { 82 xpath.setFunctionContext(functionContext); 83 } 84 85 public NamespaceContext getNamespaceContext() { 86 return namespaceContext; 87 } 88 89 public void setNamespaceURIs(Map map) { 90 setNamespaceContext(new SimpleNamespaceContext(map)); 91 } 92 93 public void setNamespaceContext(NamespaceContext namespaceContext) { 94 this.namespaceContext = namespaceContext; 95 xpath.setNamespaceContext(namespaceContext); 96 } 97 98 public VariableContext getVariableContext() { 99 return xpath.getVariableContext(); 100 } 101 102 public void setVariableContext(VariableContext variableContext) { 103 xpath.setVariableContext(variableContext); 104 } 105 106 public Object evaluate(Object context) { 107 try { 108 setNSContext(context); 109 110 List answer = xpath.selectNodes(context); 111 112 if ((answer != null) && (answer.size() == 1)) { 113 return answer.get(0); 114 } 115 116 return answer; 117 } catch (JaxenException e) { 118 handleJaxenException(e); 119 120 return null; 121 } 122 } 123 124 public Object selectObject(Object context) { 125 return evaluate(context); 126 } 127 128 public List selectNodes(Object context) { 129 try { 130 setNSContext(context); 131 132 return xpath.selectNodes(context); 133 } catch (JaxenException e) { 134 handleJaxenException(e); 135 136 return Collections.EMPTY_LIST; 137 } 138 } 139 140 public List selectNodes(Object context, org.dom4j.XPath sortXPath) { 141 List answer = selectNodes(context); 142 sortXPath.sort(answer); 143 144 return answer; 145 } 146 147 public List selectNodes(Object context, org.dom4j.XPath sortXPath, 148 boolean distinct) { 149 List answer = selectNodes(context); 150 sortXPath.sort(answer, distinct); 151 152 return answer; 153 } 154 155 public Node selectSingleNode(Object context) { 156 try { 157 setNSContext(context); 158 159 Object answer = xpath.selectSingleNode(context); 160 161 if (answer instanceof Node) { 162 return (Node) answer; 163 } 164 165 if (answer == null) { 166 return null; 167 } 168 169 throw new XPathException("The result of the XPath expression is " 170 + "not a Node. It was: " + answer + " of type: " 171 + answer.getClass().getName()); 172 } catch (JaxenException e) { 173 handleJaxenException(e); 174 175 return null; 176 } 177 } 178 179 public String valueOf(Object context) { 180 try { 181 setNSContext(context); 182 183 return xpath.stringValueOf(context); 184 } catch (JaxenException e) { 185 handleJaxenException(e); 186 187 return ""; 188 } 189 } 190 191 public Number numberValueOf(Object context) { 192 try { 193 setNSContext(context); 194 195 return xpath.numberValueOf(context); 196 } catch (JaxenException e) { 197 handleJaxenException(e); 198 199 return null; 200 } 201 } 202 203 public boolean booleanValueOf(Object context) { 204 try { 205 setNSContext(context); 206 207 return xpath.booleanValueOf(context); 208 } catch (JaxenException e) { 209 handleJaxenException(e); 210 211 return false; 212 } 213 } 214 215 224 public void sort(List list) { 225 sort(list, false); 226 } 227 228 240 public void sort(List list, boolean distinct) { 241 if ((list != null) && !list.isEmpty()) { 242 int size = list.size(); 243 HashMap sortValues = new HashMap (size); 244 245 for (int i = 0; i < size; i++) { 246 Object object = list.get(i); 247 248 if (object instanceof Node) { 249 Node node = (Node) object; 250 Object expression = getCompareValue(node); 251 sortValues.put(node, expression); 252 } 253 } 254 255 sort(list, sortValues); 256 257 if (distinct) { 258 removeDuplicates(list, sortValues); 259 } 260 } 261 } 262 263 public boolean matches(Node node) { 264 try { 265 setNSContext(node); 266 267 List answer = xpath.selectNodes(node); 268 269 if ((answer != null) && (answer.size() > 0)) { 270 Object item = answer.get(0); 271 272 if (item instanceof Boolean ) { 273 return ((Boolean ) item).booleanValue(); 274 } 275 276 return answer.contains(node); 277 } 278 279 return false; 280 } catch (JaxenException e) { 281 handleJaxenException(e); 282 283 return false; 284 } 285 } 286 287 295 protected void sort(List list, final Map sortValues) { 296 Collections.sort(list, new Comparator () { 297 public int compare(Object o1, Object o2) { 298 o1 = sortValues.get(o1); 299 o2 = sortValues.get(o2); 300 301 if (o1 == o2) { 302 return 0; 303 } else if (o1 instanceof Comparable ) { 304 Comparable c1 = (Comparable ) o1; 305 306 return c1.compareTo(o2); 307 } else if (o1 == null) { 308 return 1; 309 } else if (o2 == null) { 310 return -1; 311 } else { 312 return o1.equals(o2) ? 0 : (-1); 313 } 314 } 315 }); 316 } 317 318 320 328 protected void removeDuplicates(List list, Map sortValues) { 329 HashSet distinctValues = new HashSet (); 331 332 for (Iterator iter = list.iterator(); iter.hasNext();) { 333 Object node = iter.next(); 334 Object value = sortValues.get(node); 335 336 if (distinctValues.contains(value)) { 337 iter.remove(); 338 } else { 339 distinctValues.add(value); 340 } 341 } 342 } 343 344 352 protected Object getCompareValue(Node node) { 353 return valueOf(node); 354 } 355 356 protected static XPath parse(String text) { 357 try { 358 return new Dom4jXPath(text); 359 } catch (JaxenException e) { 360 throw new InvalidXPathException(text, e.getMessage()); 361 } catch (Throwable t) { 362 throw new InvalidXPathException(text, t); 363 } 364 } 365 366 protected void setNSContext(Object context) { 367 if (namespaceContext == null) { 368 xpath.setNamespaceContext(DefaultNamespaceContext.create(context)); 369 } 370 } 371 372 protected void handleJaxenException(JaxenException exception) 373 throws XPathException { 374 throw new XPathException(text, exception); 375 } 376 } 377 378 414 | Popular Tags |