1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.xpath;
17
18 import java.util.Comparator;
19 import java.util.List;
20
21 import org.apache.commons.jelly.util.NestedRuntimeException;
22 import org.dom4j.Node;
23 import org.jaxen.JaxenException;
24 import org.jaxen.XPath;
25
26 /***
27 * Compares xml nodes by extracting the value at xpath and
28 * comparing it.
29 *
30 * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
31 * @version $Id: XPathComparator.java 155420 2005-02-26 13:06:03Z dirkv $
32 */
33
34 public class XPathComparator implements Comparator {
35
36 /*** The xpath to use to extract value from nodes to compare */
37 private XPath xpath = null;
38
39 /*** Sort descending or ascending */
40 private boolean descending = false;
41
42 public XPathComparator() {
43
44 }
45
46 public XPathComparator(XPath xpath, boolean descending) {
47 this.xpath = xpath;
48 this.descending = descending;
49 }
50
51 public void setXpath(XPath xpath) {
52 this.xpath = xpath;
53 }
54
55 public XPath getXpath() {
56 return xpath;
57 }
58
59 public void setDescending(boolean descending) {
60 this.descending = descending;
61 }
62
63 public int compare(Object o1, Object o2) {
64 return compare((Node)o1, (Node)o2);
65 }
66
67 public int compare(Node n1, Node n2) {
68 try {
69
70
71
72 Object val1 = xpath.evaluate(n1);
73 Object val2 = xpath.evaluate(n2);
74
75
76 if (val1 == null || val2 == null) {
77 return val1 == null ? (val2 == null ? 1 : -1) : 1;
78 }
79
80 Comparable c1 = getComparableValue(val1);
81 Comparable c2 = getComparableValue(val2);
82
83
84 if (!descending) {
85 return c1.compareTo(c2);
86 } else {
87 return c2.compareTo(c1);
88 }
89
90 } catch (JaxenException e) {
91
92 throw new XPathSortException("error sorting nodes", e);
93
94 }
95 }
96
97 /***
98 * Turns the XPath result value into a Comparable object.
99 */
100 protected Comparable getComparableValue(Object value) {
101 if (value instanceof List) {
102 List list = (List) value;
103 if (list.isEmpty()) {
104 value = "";
105 }
106 value = list.get(0);
107 if (value == null) {
108 value = "";
109 }
110 }
111 if (value instanceof Comparable) {
112 return (Comparable) value;
113 }
114 else if (value instanceof Node) {
115 Node node = (Node) value;
116 return node.getStringValue();
117 }
118 return value.toString();
119 }
120
121 /***
122 * My own runtime exception in case something goes wrong with sort.
123 */
124 public static class XPathSortException extends NestedRuntimeException {
125 public XPathSortException(String message, Throwable cause) {
126 super(message, cause);
127 }
128 }
129 }