Source Code Cross Referenced for NodePointer.java in  » Library » Apache-commons-jxpath-1.2-src » org » apache » commons » jxpath » ri » model » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons jxpath 1.2 src » org.apache.commons.jxpath.ri.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 1999-2004 The Apache Software Foundation
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.apache.commons.jxpath.ri.model;
017:
018:        import java.util.Locale;
019:
020:        import org.apache.commons.jxpath.JXPathContext;
021:        import org.apache.commons.jxpath.JXPathException;
022:        import org.apache.commons.jxpath.Pointer;
023:        import org.apache.commons.jxpath.ri.Compiler;
024:        import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
025:        import org.apache.commons.jxpath.ri.NamespaceResolver;
026:        import org.apache.commons.jxpath.ri.QName;
027:        import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
028:        import org.apache.commons.jxpath.ri.compiler.NodeTest;
029:        import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
030:        import org.apache.commons.jxpath.ri.model.beans.NullPointer;
031:
032:        /**
033:         * Common superclass for Pointers of all kinds.  A NodePointer maps to
034:         * a deterministic XPath that represents the location of a node in an 
035:         * object graph. This XPath uses only simple axes: child, namespace and
036:         * attribute and only simple, context-independent predicates.
037:         *
038:         * @author Dmitri Plotnikov
039:         * @version $Revision: 1.25 $ $Date: 2004/04/01 02:55:32 $
040:         */
041:        public abstract class NodePointer implements  Pointer {
042:
043:            public static final int WHOLE_COLLECTION = Integer.MIN_VALUE;
044:            protected int index = WHOLE_COLLECTION;
045:            public static final String UNKNOWN_NAMESPACE = "<<unknown namespace>>";
046:            private boolean attribute = false;
047:            private transient Object rootNode;
048:            private NamespaceResolver namespaceResolver;
049:
050:            /**
051:             * Allocates an entirely new NodePointer by iterating through all installed
052:             * NodePointerFactories until it finds one that can create a pointer.
053:             */
054:            public static NodePointer newNodePointer(QName name, Object bean,
055:                    Locale locale) {
056:                NodePointer pointer = null;
057:                if (bean == null) {
058:                    pointer = new NullPointer(name, locale);
059:                    return pointer;
060:                }
061:
062:                NodePointerFactory[] factories = JXPathContextReferenceImpl
063:                        .getNodePointerFactories();
064:                for (int i = 0; i < factories.length; i++) {
065:                    pointer = factories[i]
066:                            .createNodePointer(name, bean, locale);
067:                    if (pointer != null) {
068:                        return pointer;
069:                    }
070:                }
071:                throw new JXPathException(
072:                        "Could not allocate a NodePointer for object of "
073:                                + bean.getClass());
074:            }
075:
076:            /**
077:             * Allocates an new child NodePointer by iterating through all installed
078:             * NodePointerFactories until it finds one that can create a pointer.
079:             */
080:            public static NodePointer newChildNodePointer(NodePointer parent,
081:                    QName name, Object bean) {
082:                NodePointerFactory[] factories = JXPathContextReferenceImpl
083:                        .getNodePointerFactories();
084:                for (int i = 0; i < factories.length; i++) {
085:                    NodePointer pointer = factories[i].createNodePointer(
086:                            parent, name, bean);
087:                    if (pointer != null) {
088:                        return pointer;
089:                    }
090:                }
091:                throw new JXPathException(
092:                        "Could not allocate a NodePointer for object of "
093:                                + bean.getClass());
094:            }
095:
096:            protected NodePointer parent;
097:            protected Locale locale;
098:
099:            //    private NamespaceManager namespaceManager;
100:
101:            protected NodePointer(NodePointer parent) {
102:                this .parent = parent;
103:            }
104:
105:            protected NodePointer(NodePointer parent, Locale locale) {
106:                this .parent = parent;
107:                this .locale = locale;
108:            }
109:
110:            public NamespaceResolver getNamespaceResolver() {
111:                if (namespaceResolver == null && parent != null) {
112:                    namespaceResolver = parent.getNamespaceResolver();
113:                }
114:                return namespaceResolver;
115:            }
116:
117:            public void setNamespaceResolver(NamespaceResolver namespaceResolver) {
118:                this .namespaceResolver = namespaceResolver;
119:            }
120:
121:            public NodePointer getParent() {
122:                NodePointer pointer = parent;
123:                while (pointer != null && pointer.isContainer()) {
124:                    pointer = pointer.getImmediateParentPointer();
125:                }
126:                return pointer;
127:            }
128:
129:            public NodePointer getImmediateParentPointer() {
130:                return parent;
131:            }
132:
133:            /**
134:             * Set to true if the pointer represents the "attribute::" axis.
135:             */
136:            public void setAttribute(boolean attribute) {
137:                this .attribute = attribute;
138:            }
139:
140:            /**
141:             * Returns true if the pointer represents the "attribute::" axis.
142:             */
143:            public boolean isAttribute() {
144:                return attribute;
145:            }
146:
147:            /**
148:             * Returns true if this Pointer has no parent.
149:             */
150:            public boolean isRoot() {
151:                return parent == null;
152:            }
153:
154:            /**
155:             * If true, this node does not have children
156:             */
157:            public abstract boolean isLeaf();
158:
159:            /**
160:             * @deprecated Please use !isContainer()
161:             */
162:            public boolean isNode() {
163:                return !isContainer();
164:            }
165:
166:            /**
167:             * If true, this node is axiliary and can only be used as an intermediate in
168:             * the chain of pointers.
169:             */
170:            public boolean isContainer() {
171:                return false;
172:            }
173:
174:            /**
175:             * If the pointer represents a collection, the index identifies
176:             * an element of that collection.  The default value of <code>index</code>
177:             * is <code>WHOLE_COLLECTION</code>, which just means that the pointer
178:             * is not indexed at all.
179:             * Note: the index on NodePointer starts with 0, not 1.
180:             */
181:            public int getIndex() {
182:                return index;
183:            }
184:
185:            public void setIndex(int index) {
186:                this .index = index;
187:            }
188:
189:            /**
190:             * Returns <code>true</code> if the value of the pointer is an array or
191:             * a Collection.
192:             */
193:            public abstract boolean isCollection();
194:
195:            /**
196:             * If the pointer represents a collection (or collection element),
197:             * returns the length of the collection.
198:             * Otherwise returns 1 (even if the value is null).
199:             */
200:            public abstract int getLength();
201:
202:            /**
203:             * By default, returns <code>getNode()</code>, can be overridden to
204:             * return a "canonical" value, like for instance a DOM element should
205:             * return its string value.
206:             */
207:            public Object getValue() {
208:                NodePointer valuePointer = getValuePointer();
209:                if (valuePointer != this ) {
210:                    return valuePointer.getValue();
211:                }
212:                // Default behavior is to return the same as getNode() 
213:                return getNode();
214:            }
215:
216:            /**
217:             * If this pointer manages a transparent container, like a variable,
218:             * this method returns the pointer to the contents.
219:             * Only an auxiliary (non-node) pointer can (and should) return a
220:             * value pointer other than itself.
221:             * Note that you probably don't want to override 
222:             * <code>getValuePointer()</code> directly.  Override the
223:             * <code>getImmediateValuePointer()</code> method instead.  The
224:             * <code>getValuePointer()</code> method is calls
225:             * <code>getImmediateValuePointer()</code> and, if the result is not
226:             * <code>this</code>, invokes <code>getValuePointer()</code> recursively.
227:             * The idea here is to open all nested containers. Let's say we have a
228:             * container within a container within a container. The
229:             * <code>getValuePointer()</code> method should then open all those
230:             * containers and return the pointer to the ultimate contents. It does so
231:             * with the above recursion.
232:             */
233:            public NodePointer getValuePointer() {
234:                NodePointer ivp = getImmediateValuePointer();
235:                if (ivp != this ) {
236:                    return ivp.getValuePointer();
237:                }
238:                return this ;
239:            }
240:
241:            /**
242:             * @see #getValuePointer()
243:             * 
244:             * @return NodePointer is either <code>this</code> or a pointer
245:             *   for the immediately contained value.
246:             */
247:            public NodePointer getImmediateValuePointer() {
248:                return this ;
249:            }
250:
251:            /**
252:             * An actual pointer points to an existing part of an object graph, even
253:             * if it is null. A non-actual pointer represents a part that does not exist
254:             * at all.
255:             * For instance consider the pointer "/address/street".
256:             * If both <em>address</em> and <em>street</em> are not null,
257:             * the pointer is actual.
258:             * If <em>address</em> is not null, but <em>street</em> is null,
259:             * the pointer is still actual.
260:             * If <em>address</em> is null, the pointer is not actual.
261:             * (In JavaBeans) if <em>address</em> is not a property of the root bean,
262:             * a Pointer for this path cannot be obtained at all - actual or otherwise.
263:             */
264:            public boolean isActual() {
265:                if (index == WHOLE_COLLECTION) {
266:                    return true;
267:                } else {
268:                    return index >= 0 && index < getLength();
269:                }
270:            }
271:
272:            /**
273:             * Returns the name of this node. Can be null.
274:             */
275:            public abstract QName getName();
276:
277:            /**
278:             * Returns the value represented by the pointer before indexing.
279:             * So, if the node represents an element of a collection, this
280:             * method returns the collection itself.
281:             */
282:            public abstract Object getBaseValue();
283:
284:            /**
285:             * Returns the object the pointer points to; does not convert it
286:             * to a "canonical" type.
287:             *
288:             * @deprecated 1.1 Please use getNode()
289:             */
290:            public Object getNodeValue() {
291:                return getNode();
292:            }
293:
294:            /**
295:             * Returns the object the pointer points to; does not convert it
296:             * to a "canonical" type. Opens containers, properties etc and returns
297:             * the ultimate contents.
298:             */
299:            public Object getNode() {
300:                return getValuePointer().getImmediateNode();
301:            }
302:
303:            public Object getRootNode() {
304:                if (rootNode == null) {
305:                    if (parent != null) {
306:                        rootNode = parent.getRootNode();
307:                    } else {
308:                        rootNode = getImmediateNode();
309:                    }
310:                }
311:                return rootNode;
312:            }
313:
314:            /**
315:             * Returns the object the pointer points to; does not convert it
316:             * to a "canonical" type.
317:             */
318:            public abstract Object getImmediateNode();
319:
320:            /**
321:             * Converts the value to the required type and changes the corresponding
322:             * object to that value.
323:             */
324:            public abstract void setValue(Object value);
325:
326:            /**
327:             * Compares two child NodePointers and returns a positive number,
328:             * zero or a positive number according to the order of the pointers.
329:             */
330:            public abstract int compareChildNodePointers(NodePointer pointer1,
331:                    NodePointer pointer2);
332:
333:            /**
334:             * Checks if this Pointer matches the supplied NodeTest.
335:             */
336:            public boolean testNode(NodeTest test) {
337:                if (test == null) {
338:                    return true;
339:                } else if (test instanceof  NodeNameTest) {
340:                    if (isContainer()) {
341:                        return false;
342:                    }
343:                    NodeNameTest nodeNameTest = (NodeNameTest) test;
344:                    QName testName = nodeNameTest.getNodeName();
345:                    QName nodeName = getName();
346:                    if (nodeName == null) {
347:                        return false;
348:                    }
349:
350:                    String testPrefix = testName.getPrefix();
351:                    String nodePrefix = nodeName.getPrefix();
352:                    if (!equalStrings(testPrefix, nodePrefix)) {
353:                        String testNS = getNamespaceURI(testPrefix);
354:                        String nodeNS = getNamespaceURI(nodePrefix);
355:                        if (!equalStrings(testNS, nodeNS)) {
356:                            return false;
357:                        }
358:                    }
359:                    if (nodeNameTest.isWildcard()) {
360:                        return true;
361:                    }
362:                    return testName.getName().equals(nodeName.getName());
363:                } else if (test instanceof  NodeTypeTest) {
364:                    if (((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_NODE) {
365:                        return isNode();
366:                    }
367:                }
368:                return false;
369:            }
370:
371:            private static boolean equalStrings(String s1, String s2) {
372:                if (s1 == null && s2 != null) {
373:                    return false;
374:                }
375:                if (s1 != null && !s1.equals(s2)) {
376:                    return false;
377:                }
378:                return true;
379:            }
380:
381:            /**
382:             *  Called directly by JXPathContext. Must create path and
383:             *  set value.
384:             */
385:            public NodePointer createPath(JXPathContext context, Object value) {
386:                setValue(value);
387:                return this ;
388:            }
389:
390:            /**
391:             * Remove the node of the object graph this pointer points to.
392:             */
393:            public void remove() {
394:                // It is a no-op
395:
396:                //        System.err.println("REMOVING: " + asPath() + " " + getClass());
397:                //        printPointerChain();
398:            }
399:
400:            /**
401:             * Called by a child pointer when it needs to create a parent object.
402:             * Must create an object described by this pointer and return
403:             * a new pointer that properly describes the new object.
404:             */
405:            public NodePointer createPath(JXPathContext context) {
406:                return this ;
407:            }
408:
409:            /**
410:             * Called by a child pointer if that child needs to assign the value
411:             * supplied in the createPath(context, value) call to a non-existent
412:             * node. This method may have to expand the collection in order to assign
413:             * the element.
414:             */
415:            public NodePointer createChild(JXPathContext context, QName name,
416:                    int index, Object value) {
417:                throw new JXPathException("Cannot create an object for path "
418:                        + asPath() + "/" + name + "[" + (index + 1) + "]"
419:                        + ", operation is not allowed for this type of node");
420:            }
421:
422:            /**
423:             * Called by a child pointer when it needs to create a parent object
424:             * for a non-existent collection element.  It may have to expand the
425:             * collection, then create an element object and return a new pointer
426:             * describing the newly created element.
427:             */
428:            public NodePointer createChild(JXPathContext context, QName name,
429:                    int index) {
430:                throw new JXPathException("Cannot create an object for path "
431:                        + asPath() + "/" + name + "[" + (index + 1) + "]"
432:                        + ", operation is not allowed for this type of node");
433:            }
434:
435:            /**
436:             * Called to create a non-existing attribute
437:             */
438:            public NodePointer createAttribute(JXPathContext context, QName name) {
439:                throw new JXPathException(
440:                        "Cannot create an attribute for path "
441:                                + asPath()
442:                                + "/@"
443:                                + name
444:                                + ", operation is not allowed for this type of node");
445:            }
446:
447:            /**
448:             * If the Pointer has a parent, returns the parent's locale;
449:             * otherwise returns the locale specified when this Pointer
450:             * was created.
451:             */
452:            public Locale getLocale() {
453:                if (locale == null) {
454:                    if (parent != null) {
455:                        locale = parent.getLocale();
456:                    }
457:                }
458:                return locale;
459:            }
460:
461:            /**
462:             * Returns true if the selected locale name starts
463:             * with the specified prefix <i>lang</i>, case-insensitive.
464:             */
465:            public boolean isLanguage(String lang) {
466:                Locale loc = getLocale();
467:                String name = loc.toString().replace('_', '-');
468:                return name.toUpperCase().startsWith(lang.toUpperCase());
469:            }
470:
471:            //    /**
472:            //     * Installs the supplied manager as the namespace manager for this node
473:            //     * pointer. The {@link #getNamespaceURI(String) getNamespaceURI(prefix)}
474:            //     * uses this manager to resolve namespace prefixes.
475:            //     * 
476:            //     * @param namespaceManager
477:            //     */
478:            //    public void setNamespaceManager(NamespaceManager namespaceManager) {
479:            //        this.namespaceManager = namespaceManager;
480:            //    }
481:            //    
482:            //    public NamespaceManager getNamespaceManager() {
483:            //        if (namespaceManager != null) {
484:            //            return namespaceManager;
485:            //        }
486:            //        if (parent != null) {
487:            //            return parent.getNamespaceManager();
488:            //        }        
489:            //        return null;
490:            //    }
491:            //    
492:            /**
493:             * Returns a NodeIterator that iterates over all children or all children
494:             * that match the given NodeTest, starting with the specified one.
495:             */
496:            public NodeIterator childIterator(NodeTest test, boolean reverse,
497:                    NodePointer startWith) {
498:                NodePointer valuePointer = getValuePointer();
499:                if (valuePointer != null && valuePointer != this ) {
500:                    return valuePointer.childIterator(test, reverse, startWith);
501:                }
502:                return null;
503:            }
504:
505:            /**
506:             * Returns a NodeIterator that iterates over all attributes of the current
507:             * node matching the supplied node name (could have a wildcard).
508:             * May return null if the object does not support the attributes.
509:             */
510:            public NodeIterator attributeIterator(QName qname) {
511:                NodePointer valuePointer = getValuePointer();
512:                if (valuePointer != null && valuePointer != this ) {
513:                    return valuePointer.attributeIterator(qname);
514:                }
515:                return null;
516:            }
517:
518:            /**
519:             * Returns a NodeIterator that iterates over all namespaces of the value
520:             * currently pointed at.
521:             * May return null if the object does not support the namespaces.
522:             */
523:            public NodeIterator namespaceIterator() {
524:                return null;
525:            }
526:
527:            /**
528:             * Returns a NodePointer for the specified namespace. Will return null
529:             * if namespaces are not supported.
530:             * Will return UNKNOWN_NAMESPACE if there is no such namespace.
531:             */
532:            public NodePointer namespacePointer(String namespace) {
533:                return null;
534:            }
535:
536:            /**
537:             * Decodes a namespace prefix to the corresponding URI.
538:             */
539:            public String getNamespaceURI(String prefix) {
540:                return null;
541:            }
542:
543:            /**
544:             * Returns the namespace URI associated with this Pointer.
545:             */
546:            public String getNamespaceURI() {
547:                return null;
548:            }
549:
550:            /**
551:             * Returns true if the supplied prefix represents the
552:             * default namespace in the context of the current node.
553:             */
554:            protected boolean isDefaultNamespace(String prefix) {
555:                if (prefix == null) {
556:                    return true;
557:                }
558:
559:                String namespace = getNamespaceURI(prefix);
560:                if (namespace == null) {
561:                    return false; // undefined namespace
562:                }
563:
564:                return namespace.equals(getDefaultNamespaceURI());
565:            }
566:
567:            protected String getDefaultNamespaceURI() {
568:                return null;
569:            }
570:
571:            /**
572:             * Locates a node by ID.
573:             */
574:            public Pointer getPointerByID(JXPathContext context, String id) {
575:                return context.getPointerByID(id);
576:            }
577:
578:            /**
579:             * Locates a node by key and value.
580:             */
581:            public Pointer getPointerByKey(JXPathContext context, String key,
582:                    String value) {
583:                return context.getPointerByKey(key, value);
584:            }
585:
586:            /**
587:             * Returns an XPath that maps to this Pointer.
588:             */
589:            public String asPath() {
590:                // If the parent of this node is a container, it is responsible
591:                // for appended this node's part of the path.
592:                if (parent != null && parent.isContainer()) {
593:                    return parent.asPath();
594:                }
595:
596:                StringBuffer buffer = new StringBuffer();
597:                if (parent != null) {
598:                    buffer.append(parent.asPath());
599:                }
600:
601:                if (buffer.length() == 0
602:                        || buffer.charAt(buffer.length() - 1) != '/') {
603:                    buffer.append('/');
604:                }
605:                if (attribute) {
606:                    buffer.append('@');
607:                }
608:                buffer.append(getName());
609:
610:                if (index != WHOLE_COLLECTION && isCollection()) {
611:                    buffer.append('[').append(index + 1).append(']');
612:                }
613:                return buffer.toString();
614:            }
615:
616:            public Object clone() {
617:                try {
618:                    NodePointer ptr = (NodePointer) super .clone();
619:                    if (parent != null) {
620:                        ptr.parent = (NodePointer) parent.clone();
621:                    }
622:                    return ptr;
623:                } catch (CloneNotSupportedException ex) {
624:                    // Of course it is supported
625:                    ex.printStackTrace();
626:                }
627:                return null;
628:            }
629:
630:            public String toString() {
631:                return asPath();
632:            }
633:
634:            public int compareTo(Object object) {
635:                // Let it throw a ClassCastException
636:                NodePointer pointer = (NodePointer) object;
637:                if (parent == pointer.parent) {
638:                    if (parent == null) {
639:                        return 0;
640:                    }
641:                    return parent.compareChildNodePointers(this , pointer);
642:                }
643:
644:                // Task 1: find the common parent
645:                int depth1 = 0;
646:                NodePointer p1 = this ;
647:                while (p1 != null) {
648:                    depth1++;
649:                    p1 = p1.parent;
650:                }
651:                int depth2 = 0;
652:                NodePointer p2 = pointer;
653:                while (p2 != null) {
654:                    depth2++;
655:                    p2 = p2.parent;
656:                }
657:                return compareNodePointers(this , depth1, pointer, depth2);
658:            }
659:
660:            private int compareNodePointers(NodePointer p1, int depth1,
661:                    NodePointer p2, int depth2) {
662:                if (depth1 < depth2) {
663:                    int r = compareNodePointers(p1, depth1, p2.parent,
664:                            depth2 - 1);
665:                    if (r != 0) {
666:                        return r;
667:                    }
668:                    return -1;
669:                } else if (depth1 > depth2) {
670:                    int r = compareNodePointers(p1.parent, depth1 - 1, p2,
671:                            depth2);
672:                    if (r != 0) {
673:                        return r;
674:                    }
675:                    return 1;
676:                }
677:                if (p1 == null && p2 == null) {
678:                    return 0;
679:                }
680:
681:                if (p1 != null && p1.equals(p2)) {
682:                    return 0;
683:                }
684:
685:                if (depth1 == 1) {
686:                    throw new JXPathException(
687:                            "Cannot compare pointers that do not belong to the same tree: '"
688:                                    + p1 + "' and '" + p2 + "'");
689:                }
690:                int r = compareNodePointers(p1.parent, depth1 - 1, p2.parent,
691:                        depth2 - 1);
692:                if (r != 0) {
693:                    return r;
694:                }
695:
696:                return p1.parent.compareChildNodePointers(p1, p2);
697:            }
698:
699:            /**
700:             * Print internal structure of a pointer for debugging
701:             */
702:            public void printPointerChain() {
703:                printDeep(this , "");
704:            }
705:
706:            private static void printDeep(NodePointer pointer, String indent) {
707:                if (indent.length() == 0) {
708:                    System.err.println("POINTER: " + pointer + "("
709:                            + pointer.getClass().getName() + ")");
710:                } else {
711:                    System.err.println(indent + " of " + pointer + "("
712:                            + pointer.getClass().getName() + ")");
713:                }
714:                if (pointer.getImmediateParentPointer() != null) {
715:                    printDeep(pointer.getImmediateParentPointer(), indent
716:                            + "  ");
717:                }
718:            }
719:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.