KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jxpath > ri > model > jdom > JDOMNodePointer


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.jxpath.ri.model.jdom;
17
18 import java.util.List JavaDoc;
19 import java.util.Locale JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.apache.commons.jxpath.AbstractFactory;
23 import org.apache.commons.jxpath.JXPathContext;
24 import org.apache.commons.jxpath.JXPathException;
25 import org.apache.commons.jxpath.ri.Compiler;
26 import org.apache.commons.jxpath.ri.QName;
27 import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
28 import org.apache.commons.jxpath.ri.compiler.NodeTest;
29 import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
30 import org.apache.commons.jxpath.ri.compiler.ProcessingInstructionTest;
31 import org.apache.commons.jxpath.ri.model.NodeIterator;
32 import org.apache.commons.jxpath.ri.model.NodePointer;
33 import org.apache.commons.jxpath.util.TypeUtils;
34 import org.jdom.Attribute;
35 import org.jdom.CDATA;
36 import org.jdom.Comment;
37 import org.jdom.Document;
38 import org.jdom.Element;
39 import org.jdom.Namespace;
40 import org.jdom.ProcessingInstruction;
41 import org.jdom.Text;
42
43 /**
44  * A Pointer that points to a DOM node.
45  *
46  * @author Dmitri Plotnikov
47  * @version $Revision: 1.17 $ $Date: 2004/06/29 22:58:18 $
48  */

49 public class JDOMNodePointer extends NodePointer {
50     private Object JavaDoc node;
51     private Map JavaDoc namespaces;
52     private String JavaDoc defaultNamespace;
53     private String JavaDoc id;
54
55     public static final String JavaDoc XML_NAMESPACE_URI =
56             "http://www.w3.org/XML/1998/namespace";
57     public static final String JavaDoc XMLNS_NAMESPACE_URI =
58             "http://www.w3.org/2000/xmlns/";
59
60     public JDOMNodePointer(Object JavaDoc node, Locale JavaDoc locale) {
61         super(null, locale);
62         this.node = node;
63     }
64
65     public JDOMNodePointer(Object JavaDoc node, Locale JavaDoc locale, String JavaDoc id) {
66         super(null, locale);
67         this.node = node;
68         this.id = id;
69     }
70
71     public JDOMNodePointer(NodePointer parent, Object JavaDoc node) {
72         super(parent);
73         this.node = node;
74     }
75
76     public NodeIterator childIterator(
77         NodeTest test,
78         boolean reverse,
79         NodePointer startWith)
80     {
81         return new JDOMNodeIterator(this, test, reverse, startWith);
82     }
83
84     public NodeIterator attributeIterator(QName name) {
85         return new JDOMAttributeIterator(this, name);
86     }
87
88     public NodeIterator namespaceIterator() {
89         return new JDOMNamespaceIterator(this);
90     }
91
92     public NodePointer namespacePointer(String JavaDoc prefix) {
93         return new JDOMNamespacePointer(this, prefix);
94     }
95
96     public String JavaDoc getNamespaceURI() {
97         return getNamespaceURI(node);
98     }
99     
100     private static String JavaDoc getNamespaceURI(Object JavaDoc node) {
101         if (node instanceof Element) {
102             Element element = (Element) node;
103             String JavaDoc ns = element.getNamespaceURI();
104             if (ns != null && ns.equals("")) {
105                 ns = null;
106             }
107             return ns;
108         }
109         return null;
110     }
111
112     public String JavaDoc getNamespaceURI(String JavaDoc prefix) {
113         if (node instanceof Document) {
114             Element element = ((Document)node).getRootElement();
115             Namespace ns = element.getNamespace(prefix);
116             if (ns != null) {
117                 return ns.getURI();
118             }
119         }
120         else if (node instanceof Element) {
121             Element element = (Element) node;
122             Namespace ns = element.getNamespace(prefix);
123             if (ns != null) {
124                 return ns.getURI();
125             }
126         }
127         return null;
128     }
129
130     public int compareChildNodePointers(
131         NodePointer pointer1,
132         NodePointer pointer2)
133     {
134         Object JavaDoc node1 = pointer1.getBaseValue();
135         Object JavaDoc node2 = pointer2.getBaseValue();
136         if (node1 == node2) {
137             return 0;
138         }
139
140         if ((node1 instanceof Attribute) && !(node2 instanceof Attribute)) {
141             return -1;
142         }
143         else if (
144             !(node1 instanceof Attribute) && (node2 instanceof Attribute)) {
145             return 1;
146         }
147         else if (
148             (node1 instanceof Attribute) && (node2 instanceof Attribute)) {
149             List JavaDoc list = ((Element) getNode()).getAttributes();
150             int length = list.size();
151             for (int i = 0; i < length; i++) {
152                 Object JavaDoc n = list.get(i);
153                 if (n == node1) {
154                     return -1;
155                 }
156                 else if (n == node2) {
157                     return 1;
158                 }
159             }
160             return 0; // Should not happen
161
}
162
163         if (!(node instanceof Element)) {
164             throw new RuntimeException JavaDoc(
165                 "JXPath internal error: "
166                     + "compareChildNodes called for "
167                     + node);
168         }
169
170         List JavaDoc children = ((Element) node).getContent();
171         int length = children.size();
172         for (int i = 0; i < length; i++) {
173             Object JavaDoc n = children.get(i);
174             if (n == node1) {
175                 return -1;
176             }
177             else if (n == node2) {
178                 return 1;
179             }
180         }
181
182         return 0;
183     }
184
185
186     /**
187      * @see org.apache.commons.jxpath.ri.model.NodePointer#getBaseValue()
188      */

189     public Object JavaDoc getBaseValue() {
190         return node;
191     }
192
193     public boolean isCollection() {
194         return false;
195     }
196     
197     public int getLength() {
198         return 1;
199     }
200
201     public boolean isLeaf() {
202         if (node instanceof Element) {
203             return ((Element) node).getContent().size() == 0;
204         }
205         else if (node instanceof Document) {
206             return ((Document) node).getContent().size() == 0;
207         }
208         return true;
209     }
210
211     /**
212      * @see org.apache.commons.jxpath.ri.model.NodePointer#getName()
213      */

214     public QName getName() {
215         String JavaDoc ns = null;
216         String JavaDoc ln = null;
217         if (node instanceof Element) {
218             ns = ((Element) node).getNamespacePrefix();
219             if (ns != null && ns.equals("")) {
220                 ns = null;
221             }
222             ln = ((Element) node).getName();
223         }
224         else if (node instanceof ProcessingInstruction) {
225             ln = ((ProcessingInstruction) node).getTarget();
226         }
227         return new QName(ns, ln);
228     }
229
230     /**
231      * @see org.apache.commons.jxpath.ri.model.NodePointer#getNode()
232      */

233     public Object JavaDoc getImmediateNode() {
234         return node;
235     }
236
237     public Object JavaDoc getValue() {
238         if (node instanceof Element) {
239             return ((Element) node).getTextTrim();
240         }
241         else if (node instanceof Comment) {
242             String JavaDoc text = ((Comment) node).getText();
243             if (text != null) {
244                 text = text.trim();
245             }
246             return text;
247         }
248         else if (node instanceof Text) {
249             return ((Text) node).getTextTrim();
250         }
251         else if (node instanceof CDATA) {
252             return ((CDATA) node).getTextTrim();
253         }
254         else if (node instanceof ProcessingInstruction) {
255             String JavaDoc text = ((ProcessingInstruction) node).getData();
256             if (text != null) {
257                 text = text.trim();
258             }
259             return text;
260         }
261         return null;
262     }
263
264     public void setValue(Object JavaDoc value) {
265         if (node instanceof Text) {
266             String JavaDoc string = (String JavaDoc) TypeUtils.convert(value, String JavaDoc.class);
267             if (string != null && !string.equals("")) {
268                 ((Text) node).setText(string);
269             }
270             else {
271                 nodeParent(node).removeContent((Text) node);
272             }
273         }
274         else {
275             Element element = (Element) node;
276             element.getContent().clear();
277
278             if (value instanceof Element) {
279                 Element valueElement = (Element) value;
280                 addContent(valueElement.getContent());
281             }
282             else if (value instanceof Document) {
283                 Document valueDocument = (Document) value;
284                 addContent(valueDocument.getContent());
285             }
286             else if (value instanceof Text || value instanceof CDATA) {
287                 String JavaDoc string = ((Text) value).getText();
288                 element.addContent(new Text(string));
289             }
290             else if (value instanceof ProcessingInstruction) {
291                 ProcessingInstruction pi =
292                     (ProcessingInstruction) ((ProcessingInstruction) value)
293                         .clone();
294                 element.addContent(pi);
295             }
296             else if (value instanceof Comment) {
297                 Comment comment = (Comment) ((Comment) value).clone();
298                 element.addContent(comment);
299             }
300             else {
301                 String JavaDoc string = (String JavaDoc) TypeUtils.convert(value, String JavaDoc.class);
302                 if (string != null && !string.equals("")) {
303                     element.addContent(new Text(string));
304                 }
305             }
306         }
307     }
308       
309     private void addContent(List JavaDoc content) {
310         Element element = (Element) node;
311         int count = content.size();
312
313         for (int i = 0; i < count; i++) {
314             Object JavaDoc child = content.get(i);
315             if (child instanceof Element) {
316                 child = ((Element) child).clone();
317                 element.addContent((Element) child);
318             }
319             else if (child instanceof Text) {
320                 child = ((Text) child).clone();
321                 element.addContent((Text) child);
322             }
323             else if (node instanceof CDATA) {
324                 child = ((CDATA) child).clone();
325                 element.addContent((CDATA) child);
326             }
327             else if (node instanceof ProcessingInstruction) {
328                 child = ((ProcessingInstruction) child).clone();
329                 element.addContent((ProcessingInstruction) child);
330             }
331             else if (node instanceof Comment) {
332                 child = ((Comment) child).clone();
333                 element.addContent((Comment) child);
334             }
335         }
336     }
337     
338     public boolean testNode(NodeTest test) {
339         return testNode(this, node, test);
340     }
341
342     public static boolean testNode(
343         NodePointer pointer,
344         Object JavaDoc node,
345         NodeTest test)
346     {
347         if (test == null) {
348             return true;
349         }
350         else if (test instanceof NodeNameTest) {
351             if (!(node instanceof Element)) {
352                 return false;
353             }
354
355             NodeNameTest nodeNameTest = (NodeNameTest) test;
356             QName testName = nodeNameTest.getNodeName();
357             String JavaDoc namespaceURI = nodeNameTest.getNamespaceURI();
358             boolean wildcard = nodeNameTest.isWildcard();
359             String JavaDoc testPrefix = testName.getPrefix();
360             if (wildcard && testPrefix == null) {
361                 return true;
362             }
363
364             if (wildcard
365                 || testName.getName()
366                         .equals(JDOMNodePointer.getLocalName(node))) {
367                 String JavaDoc nodeNS = JDOMNodePointer.getNamespaceURI(node);
368                 return equalStrings(namespaceURI, nodeNS);
369             }
370
371         }
372         else if (test instanceof NodeTypeTest) {
373             switch (((NodeTypeTest) test).getNodeType()) {
374                 case Compiler.NODE_TYPE_NODE :
375                     return node instanceof Element;
376                 case Compiler.NODE_TYPE_TEXT :
377                     return (node instanceof Text) || (node instanceof CDATA);
378                 case Compiler.NODE_TYPE_COMMENT :
379                     return node instanceof Comment;
380                 case Compiler.NODE_TYPE_PI :
381                     return node instanceof ProcessingInstruction;
382             }
383             return false;
384         }
385         else if (test instanceof ProcessingInstructionTest) {
386             if (node instanceof ProcessingInstruction) {
387                 String JavaDoc testPI = ((ProcessingInstructionTest) test).getTarget();
388                 String JavaDoc nodePI = ((ProcessingInstruction) node).getTarget();
389                 return testPI.equals(nodePI);
390             }
391         }
392
393         return false;
394     }
395
396     private static boolean equalStrings(String JavaDoc s1, String JavaDoc s2) {
397         if (s1 == null && s2 != null) {
398             return false;
399         }
400         if (s1 != null && s2 == null) {
401             return false;
402         }
403
404         if (s1 != null && !s1.trim().equals(s2.trim())) {
405             return false;
406         }
407
408         return true;
409     }
410
411     public static String JavaDoc getPrefix(Object JavaDoc node) {
412         if (node instanceof Element) {
413             String JavaDoc prefix = ((Element) node).getNamespacePrefix();
414             return (prefix == null || prefix.equals("")) ? null : prefix;
415         }
416         else if (node instanceof Attribute) {
417             String JavaDoc prefix = ((Attribute) node).getNamespacePrefix();
418             return (prefix == null || prefix.equals("")) ? null : prefix;
419         }
420         return null;
421     }
422     
423     public static String JavaDoc getLocalName(Object JavaDoc node) {
424         if (node instanceof Element) {
425             return ((Element) node).getName();
426         }
427         else if (node instanceof Attribute) {
428             return ((Attribute) node).getName();
429         }
430         return null;
431     }
432
433     /**
434      * Returns true if the xml:lang attribute for the current node
435      * or its parent has the specified prefix <i>lang</i>.
436      * If no node has this prefix, calls <code>super.isLanguage(lang)</code>.
437      */

438     public boolean isLanguage(String JavaDoc lang) {
439         String JavaDoc current = getLanguage();
440         if (current == null) {
441             return super.isLanguage(lang);
442         }
443         return current.toUpperCase().startsWith(lang.toUpperCase());
444     }
445
446     protected String JavaDoc getLanguage() {
447         Object JavaDoc n = node;
448         while (n != null) {
449             if (n instanceof Element) {
450                 Element e = (Element) n;
451                 String JavaDoc attr =
452                     e.getAttributeValue("lang", Namespace.XML_NAMESPACE);
453                 if (attr != null && !attr.equals("")) {
454                     return attr;
455                 }
456             }
457             n = nodeParent(n);
458         }
459         return null;
460     }
461     
462     private Element nodeParent(Object JavaDoc node) {
463         if (node instanceof Element) {
464             Object JavaDoc parent = ((Element) node).getParent();
465             if (parent instanceof Element) {
466                 return (Element) parent;
467             }
468         }
469         else if (node instanceof Text) {
470             return (Element) ((Text) node).getParent();
471         }
472         else if (node instanceof CDATA) {
473             return (Element) ((CDATA) node).getParent();
474         }
475         else if (node instanceof ProcessingInstruction) {
476             return (Element) ((ProcessingInstruction) node).getParent();
477         }
478         else if (node instanceof Comment) {
479             return (Element) ((Comment) node).getParent();
480         }
481         return null;
482     }
483
484     public NodePointer createChild(
485         JXPathContext context,
486         QName name,
487         int index)
488     {
489         if (index == WHOLE_COLLECTION) {
490             index = 0;
491         }
492         boolean success =
493             getAbstractFactory(context).createObject(
494                 context,
495                 this,
496                 node,
497                 name.toString(),
498                 index);
499         if (success) {
500             NodeTest nodeTest;
501             String JavaDoc prefix = name.getPrefix();
502             if (prefix != null) {
503                 String JavaDoc namespaceURI = context.getNamespaceURI(prefix);
504                 nodeTest = new NodeNameTest(name, namespaceURI);
505             }
506             else {
507                 nodeTest = new NodeNameTest(name);
508             }
509
510             NodeIterator it =
511                 childIterator(nodeTest, false, null);
512             if (it != null && it.setPosition(index + 1)) {
513                 return it.getNodePointer();
514             }
515         }
516         throw new JXPathException(
517             "Factory could not create "
518                 + "a child node for path: "
519                 + asPath()
520                 + "/"
521                 + name
522                 + "["
523                 + (index + 1)
524                 + "]");
525     }
526
527     public NodePointer createChild(
528             JXPathContext context, QName name, int index, Object JavaDoc value)
529     {
530         NodePointer ptr = createChild(context, name, index);
531         ptr.setValue(value);
532         return ptr;
533     }
534
535     public NodePointer createAttribute(JXPathContext context, QName name) {
536         if (!(node instanceof Element)) {
537             return super.createAttribute(context, name);
538         }
539
540         Element element = (Element) node;
541         String JavaDoc prefix = name.getPrefix();
542         if (prefix != null) {
543             Namespace ns = element.getNamespace(prefix);
544             if (ns == null) {
545                 throw new JXPathException(
546                     "Unknown namespace prefix: " + prefix);
547             }
548             Attribute attr = element.getAttribute(name.getName(), ns);
549             if (attr == null) {
550                 element.setAttribute(name.getName(), "", ns);
551             }
552         }
553         else {
554             Attribute attr = element.getAttribute(name.getName());
555             if (attr == null) {
556                 element.setAttribute(name.getName(), "");
557             }
558         }
559         NodeIterator it = attributeIterator(name);
560         it.setPosition(1);
561         return it.getNodePointer();
562     }
563
564     public void remove() {
565         Element parent = nodeParent(node);
566         if (parent == null) {
567             throw new JXPathException("Cannot remove root JDOM node");
568         }
569         parent.getContent().remove(node);
570     }
571
572     public String JavaDoc asPath() {
573         if (id != null) {
574             return "id('" + escape(id) + "')";
575         }
576
577         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
578         if (parent != null) {
579             buffer.append(parent.asPath());
580         }
581         if (node instanceof Element) {
582             // If the parent pointer is not a JDOMNodePointer, it is
583
// the parent's responsibility to produce the node test part
584
// of the path
585
if (parent instanceof JDOMNodePointer) {
586                 if (buffer.length() == 0
587                     || buffer.charAt(buffer.length() - 1) != '/') {
588                     buffer.append('/');
589                 }
590                 String JavaDoc nsURI = getNamespaceURI();
591                 String JavaDoc ln = JDOMNodePointer.getLocalName(node);
592                 
593                 if (nsURI == null) {
594                     buffer.append(ln);
595                     buffer.append('[');
596                     buffer.append(getRelativePositionByName()).append(']');
597                 }
598                 else {
599                     String JavaDoc prefix = getNamespaceResolver().getPrefix(nsURI);
600                     if (prefix != null) {
601                         buffer.append(prefix);
602                         buffer.append(':');
603                         buffer.append(ln);
604                         buffer.append('[');
605                         buffer.append(getRelativePositionByName());
606                         buffer.append(']');
607                     }
608                     else {
609                         buffer.append("node()");
610                         buffer.append('[');
611                         buffer.append(getRelativePositionOfElement());
612                         buffer.append(']');
613                     }
614                 }
615
616             }
617         }
618         else if (node instanceof Text || node instanceof CDATA) {
619             buffer.append("/text()");
620             buffer.append('[').append(getRelativePositionOfTextNode()).append(
621                 ']');
622         }
623         else if (node instanceof ProcessingInstruction) {
624             String JavaDoc target = ((ProcessingInstruction) node).getTarget();
625             buffer.append("/processing-instruction(\'").append(target).append(
626                 "')");
627             buffer.append('[').append(getRelativePositionOfPI(target)).append(
628                 ']');
629         }
630         return buffer.toString();
631     }
632
633     private String JavaDoc escape(String JavaDoc string) {
634         int index = string.indexOf('\'');
635         while (index != -1) {
636             string =
637                 string.substring(0, index)
638                     + "&apos;"
639                     + string.substring(index + 1);
640             index = string.indexOf('\'');
641         }
642         index = string.indexOf('\"');
643         while (index != -1) {
644             string =
645                 string.substring(0, index)
646                     + "&quot;"
647                     + string.substring(index + 1);
648             index = string.indexOf('\"');
649         }
650         return string;
651     }
652
653     private int getRelativePositionByName() {
654         if (node instanceof Element) {
655             Object JavaDoc parent = ((Element) node).getParent();
656             if (!(parent instanceof Element)) {
657                 return 1;
658             }
659             
660             List JavaDoc children = ((Element)parent).getContent();
661             int count = 0;
662             String JavaDoc name = ((Element) node).getQualifiedName();
663             for (int i = 0; i < children.size(); i++) {
664                 Object JavaDoc child = children.get(i);
665                 if ((child instanceof Element)
666                     && ((Element) child).getQualifiedName().equals(name)) {
667                     count++;
668                 }
669                 if (child == node) {
670                     break;
671                 }
672             }
673             return count;
674         }
675         return 1;
676     }
677     
678     private int getRelativePositionOfElement() {
679         Element parent = (Element) ((Element) node).getParent();
680         if (parent == null) {
681             return 1;
682         }
683         List JavaDoc children = parent.getContent();
684         int count = 0;
685         for (int i = 0; i < children.size(); i++) {
686             Object JavaDoc child = children.get(i);
687             if (child instanceof Element) {
688                 count++;
689             }
690             if (child == node) {
691                 break;
692             }
693         }
694         return count;
695     }
696
697     private int getRelativePositionOfTextNode() {
698         Element parent;
699         if (node instanceof Text) {
700             parent = (Element) ((Text) node).getParent();
701         }
702         else {
703             parent = (Element) ((CDATA) node).getParent();
704         }
705         if (parent == null) {
706             return 1;
707         }
708         List JavaDoc children = parent.getContent();
709         int count = 0;
710         for (int i = 0; i < children.size(); i++) {
711             Object JavaDoc child = children.get(i);
712             if (child instanceof Text || child instanceof CDATA) {
713                 count++;
714             }
715             if (child == node) {
716                 break;
717             }
718         }
719         return count;
720     }
721
722     private int getRelativePositionOfPI(String JavaDoc target) {
723         Element parent = (Element) ((ProcessingInstruction) node).getParent();
724         if (parent == null) {
725             return 1;
726         }
727         List JavaDoc children = parent.getContent();
728         int count = 0;
729         for (int i = 0; i < children.size(); i++) {
730             Object JavaDoc child = children.get(i);
731             if (child instanceof ProcessingInstruction
732                 && (target == null
733                     || target.equals(
734                         ((ProcessingInstruction) child).getTarget()))) {
735                 count++;
736             }
737             if (child == node) {
738                 break;
739             }
740         }
741         return count;
742     }
743
744     public int hashCode() {
745         return System.identityHashCode(node);
746     }
747
748     public boolean equals(Object JavaDoc object) {
749         if (object == this) {
750             return true;
751         }
752
753         if (!(object instanceof JDOMNodePointer)) {
754             return false;
755         }
756
757         JDOMNodePointer other = (JDOMNodePointer) object;
758         return node == other.node;
759     }
760     private AbstractFactory getAbstractFactory(JXPathContext context) {
761         AbstractFactory factory = context.getFactory();
762         if (factory == null) {
763             throw new JXPathException(
764                 "Factory is not set on the JXPathContext - cannot create path: "
765                     + asPath());
766         }
767         return factory;
768     }
769 }
Popular Tags