KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > functions > DeepEqual


1 package net.sf.saxon.functions;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.expr.Expression;
4 import net.sf.saxon.expr.StaticContext;
5 import net.sf.saxon.expr.XPathContext;
6 import net.sf.saxon.om.*;
7 import net.sf.saxon.pattern.NameTest;
8 import net.sf.saxon.sort.AtomicComparer;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.type.Type;
11 import net.sf.saxon.value.BooleanValue;
12
13 /**
14 * XSLT 2.0 deep-equal() function.
15 * Supports deep comparison of two sequences (of nodes and/or atomic values)
16 * optionally using a collation
17 */

18
19 public class DeepEqual extends CollatingFunction {
20
21     private transient Configuration config = null;
22
23     /**
24     * preEvaluate: if all arguments are known statically, evaluate early
25     */

26
27     public Expression preEvaluate(StaticContext env) throws XPathException {
28         config = env.getConfiguration();
29         return super.preEvaluate(env);
30     }
31
32     /**
33     * Evaluate the expression
34     */

35
36     public Item evaluateItem(XPathContext context) throws XPathException {
37         AtomicComparer collator = getAtomicComparer(2, context);
38
39         SequenceIterator op1 = argument[0].iterate(context);
40         SequenceIterator op2 = argument[1].iterate(context);
41
42         Configuration config =
43                 (this.config!=null ? this.config : context.getController().getConfiguration());
44         return BooleanValue.get(deepEquals(op1, op2, collator, config));
45     }
46
47     /**
48      * Determine when two sequences are deep-equal
49      * @param op1 the first sequence
50      * @param op2 the second sequence
51      * @param collator the collator to be used
52      * @param config
53      * @return true if the sequences are deep-equal
54      */

55
56     public static boolean deepEquals(SequenceIterator op1, SequenceIterator op2,
57                                      AtomicComparer collator, Configuration config) {
58         boolean result = true;
59         try {
60             while (true) {
61                 Item item1 = op1.next();
62                 Item item2 = op2.next();
63
64                 if (item1 == null && item2 == null) {
65                     break;
66                 }
67
68                 if (item1 == null || item2 == null) {
69                     result = false;
70                     break;
71                 }
72
73                 if (item1 instanceof NodeInfo) {
74                     if (item2 instanceof NodeInfo) {
75                         if (!deepEquals((NodeInfo)item1, (NodeInfo)item2, collator, config)) {
76                             result = false;
77                             break;
78                         }
79                     } else {
80                         result = false;
81                         break;
82                     }
83                 } else {
84                     if (item2 instanceof NodeInfo) {
85                         result = false;
86                         break;
87                     } else {
88                         if (!collator.comparesEqual(item1, item2)) {
89                             result = false;
90                             break;
91                         }
92                     }
93                 }
94             } // end while
95

96         } catch (ClassCastException JavaDoc err) {
97             // this will happen if the sequences contain non-comparable values
98
// comparison errors are masked
99
result = false;
100         } catch (XPathException err) {
101             // comparison errors are masked
102
result = false;
103         }
104
105         return result;
106     }
107
108     /**
109     * Determine whether two nodes are deep-equal
110     */

111
112     private static boolean deepEquals(NodeInfo n1, NodeInfo n2,
113                                       AtomicComparer collator, Configuration config)
114     throws XPathException {
115         // shortcut: a node is always deep-equal to itself
116
if (n1.isSameNodeInfo(n2)) return true;
117
118         if (n1.getNodeKind() != n2.getNodeKind()) return false;
119         switch (n1.getNodeKind()) {
120             case Type.ELEMENT:
121                 if (n1.getFingerprint() != n2.getFingerprint()) {
122                     return false;
123                 }
124                 AxisIterator a1 = n1.iterateAxis(Axis.ATTRIBUTE);
125                 AxisIterator a2 = n2.iterateAxis(Axis.ATTRIBUTE);
126                 if (Aggregate.count(a1.getAnother()) != Aggregate.count(a2)) {
127                     return false;
128                 }
129                 while (true) {
130                     NodeInfo att1 = (NodeInfo)a1.next();
131                     if (att1 == null) break;
132
133                     AxisIterator a2iter = n2.iterateAxis(Axis.ATTRIBUTE,
134                                             new NameTest(Type.ATTRIBUTE, att1.getFingerprint(), config.getNamePool()));
135                     NodeInfo att2 = (NodeInfo)a2iter.next();
136
137                     if (att2==null) {
138                         return false;
139                     }
140                     if (!deepEquals(att1, att2, collator, config)) {
141                         return false;
142                     }
143                 }
144                 // fall through
145
case Type.DOCUMENT:
146                 AxisIterator c1 = n1.iterateAxis(Axis.CHILD);
147                 AxisIterator c2 = n2.iterateAxis(Axis.CHILD);
148                 while (true) {
149                     NodeInfo d1 = (NodeInfo)c1.next();
150                     while (d1 != null && (
151                             d1.getNodeKind() == Type.COMMENT ||
152                             d1.getNodeKind() == Type.PROCESSING_INSTRUCTION)) {
153                         d1 = (NodeInfo)c1.next();
154                     }
155                     NodeInfo d2 = (NodeInfo)c2.next();
156                     while (d2 != null && (
157                             d2.getNodeKind() == Type.COMMENT ||
158                             d2.getNodeKind() == Type.PROCESSING_INSTRUCTION)) {
159                         d2 = (NodeInfo)c2.next();
160                     }
161                     if (d1 == null || d2 == null) {
162                         return (d1 == d2);
163                     }
164                     if (!deepEquals(d1, d2, collator, config)) {
165                         return false;
166                     }
167                 }
168
169
170             case Type.ATTRIBUTE:
171                 if (n1.getFingerprint() != n2.getFingerprint()) {
172                     return false;
173                 }
174                 return deepEquals(n1.getTypedValue(), n2.getTypedValue(), collator, config);
175
176             case Type.PROCESSING_INSTRUCTION:
177             case Type.NAMESPACE:
178                 if (n1.getFingerprint() != n2.getFingerprint()) {
179                     return false;
180                 }
181                 // drop through
182
case Type.TEXT:
183             case Type.COMMENT:
184                 return (collator.comparesEqual(n1.getStringValue(), n2.getStringValue()));
185
186             default:
187                 throw new IllegalArgumentException JavaDoc("Unknown node type");
188         }
189     }
190
191 }
192
193 //
194
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
195
// you may not use this file except in compliance with the License. You may obtain a copy of the
196
// License at http://www.mozilla.org/MPL/
197
//
198
// Software distributed under the License is distributed on an "AS IS" basis,
199
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
200
// See the License for the specific language governing rights and limitations under the License.
201
//
202
// The Original Code is: all this file.
203
//
204
// The Initial Developer of the Original Code is Michael Kay
205
//
206
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
207
//
208
// Contributor(s): none.
209
//
210
Popular Tags