View Javadoc

1   /*
2    *  Copyright (C) 2003-2005 SINTEF
3    *  Author:  Fredrik Vraalsen (fredrik dot vraalsen at sintef dot no)
4    *  Webpage: http://coras.sourceforge.net/
5    *
6    *  This program is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public License
8    *  as published by the Free Software Foundation; either version 2.1
9    *  of the License, or (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this program; if not, write to the Free
18   *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   *  02111-1307 USA
20   */
21  package no.sintef.clix.functions;
22  
23  import java.math.BigDecimal;
24  import java.util.Collection;
25  import java.util.Iterator;
26  
27  import no.sintef.xml.XmlHelper;
28  
29  import org.apache.log4j.Logger;
30  import org.jaxen.JaxenException;
31  import org.jaxen.NamespaceContext;
32  import org.jaxen.VariableContext;
33  import org.jaxen.XPath;
34  import org.w3c.dom.Attr;
35  import org.w3c.dom.Element;
36  import org.w3c.dom.Node;
37  import org.w3c.dom.NodeList;
38  import org.w3c.dom.Text;
39  
40  public class Selector {
41  
42  	private static final Logger LOGGER = Logger.getLogger(Selector.class);
43  	
44  	public static final Collection selectNodes(Object context, XPath xpath, VariableContext variableContext, NamespaceContext namespaceContext) throws JaxenException {
45  		if (variableContext != null) {
46  			xpath.setVariableContext(variableContext);
47  		}
48  		if (namespaceContext != null) {
49  			xpath.setNamespaceContext(namespaceContext);
50  		}
51  		return xpath.selectNodes(context);
52  	}
53  	
54  	public static final String stringValueOf(Object context, XPath xpath, VariableContext variableContext, NamespaceContext namespaceContext) throws JaxenException {
55  		if (variableContext != null) {
56  			xpath.setVariableContext(variableContext);
57  		}
58  		if (namespaceContext != null) {
59  			xpath.setNamespaceContext(namespaceContext);
60  		}
61  		return xpath.stringValueOf(context);
62  	}
63  	
64  	protected static boolean equals(Collection c1, Collection c2) {
65  		// See node-set conversion rules at http://www.clixml.org/clix/1.0/#nodeset-conversion
66  		Object o1 = getCompareObject(c1);
67  		Object o2 = getCompareObject(c2);
68  		if (LOGGER.isDebugEnabled()) {
69  			LOGGER.debug("equals(" + o1 + ", " + o2 + ")");
70  		}
71  		if (o1 == o2) {
72  			return true;
73  		} else if (o1 == null || o2 == null) {
74  			return false;
75  		} 
76  		if (o1 instanceof Boolean && o2 instanceof Number) {
77  			o2 = getBooleanValue((Number)o2);
78  		} else if (o1 instanceof Number && o2 instanceof Boolean) {
79  			o1 = getBooleanValue((Number)o1);
80  		} else if (o1 instanceof Boolean && o2 instanceof String) {
81  			o1 = o1.toString();
82  		} else if (o1 instanceof String && o2 instanceof Boolean) {
83  			o2 = o2.toString();
84  		} else if (o1 instanceof String && o2 instanceof Number) {
85  			o2 = getStringValue((Number)o2);
86  		} else if (o1 instanceof Number && o2 instanceof String) {
87  			o1 = getStringValue((Number)o1);
88  		} else if (o1 instanceof String && o2 instanceof String) {
89  			// Do nothing
90  		} else {
91  			assert false : 
92  				"Unexpected compare objects: " 
93  				+ o1 + '(' + o1.getClass() + "), " 
94  				+ o2 + '(' + o2.getClass() + ')';
95  		}
96  		return o1.equals(o2);
97  	}
98  
99  	private static String getStringValue(Node node) {
100 		if (node instanceof Attr || node instanceof Text){
101 			return node.getNodeValue();
102 		} else if (node instanceof Element) {
103 			Element e = (Element) node;
104 			// FIXME is this according to spec?
105 			return XmlHelper.getText(e);
106 		} else {
107 			System.err.println("Unexpected node type: " + node + (node != null ? " [" + node.getClass() + "]" : ""));
108 			return null;
109 		}
110 	}
111 
112 	private static Object getStringValue(Number n) {
113 		if (n instanceof Float || n instanceof Double) {
114 			double d = n.doubleValue();
115 			if (Double.isNaN(d)) {
116 				return "NaN";
117 			}
118 			String s = "" + d;
119 			if (s.indexOf('.') != -1)
120 				s = s.replaceFirst(".0*$", "");
121 			return s;
122 		} else {
123 			long l = n.longValue();
124 			return "" + l;
125 		}
126 	}
127 
128 	private static Boolean getBooleanValue(Number n) {
129 		if (n instanceof Float || n instanceof Double || n instanceof BigDecimal) {
130 			double d = n.doubleValue();
131 			return Boolean.valueOf(d != 0.0 && !Double.isNaN(d));
132 		}
133 		long l = n.longValue();
134 		return Boolean.valueOf(l != 0);
135 	}
136 
137 	protected static Object getCompareObject(Collection c) {
138 		if (c == null || c.size() == 0) {
139 			return "";
140 		} else if (c.size() == 1) {
141 			Object o = c.iterator().next();
142 			if (o instanceof Node) {
143 				return getStringValue((Node)o);
144 			} else {
145 				return o;
146 			}
147 		} 
148 		// node set
149 		String result = "";
150 		for (Iterator i = c.iterator(); i.hasNext();) {
151 			Object o = (Object) i.next();
152 			if (o instanceof Node) {
153 				result += getStringValue((Node)o);
154 			} else {
155 				result += o.toString();
156 			}
157 		}
158 		return result;
159 	}
160 
161 }