1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package groovy.util.slurpersupport;
19
20 import groovy.lang.Buildable;
21 import groovy.lang.Closure;
22 import groovy.lang.DelegatingMetaClass;
23 import groovy.lang.GroovyObjectSupport;
24 import groovy.lang.MetaClass;
25 import groovy.lang.Writable;
26
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Map;
32
33
34 /***
35 * @author John Wilson
36 *
37 */
38
39 public abstract class GPathResult extends GroovyObjectSupport implements Writable, Buildable {
40 protected final GPathResult parent;
41 protected final String name;
42 protected final String namespacePrefix;
43 protected final Map namespaceMap = new HashMap();
44 protected final Map namespaceTagHints;
45
46 /***
47 * @param parent
48 * @param name
49 */
50 public GPathResult(final GPathResult parent, final String name, final String namespacePrefix, final Map namespaceTagHints) {
51 if (parent == null) {
52
53 this.parent = this;
54 this.namespaceMap.put("xml", "http://www.w3.org/XML/1998/namespace"); // The XML namespace is always defined
55 } else {
56 this.parent = parent;
57 this.namespaceMap.putAll(parent.namespaceMap);
58 }
59 this.name = name;
60 this.namespacePrefix = namespacePrefix;
61 this.namespaceTagHints = namespaceTagHints;
62
63 setMetaClass(getMetaClass());
64 }
65
66
67
68
69 public void setMetaClass(final MetaClass metaClass) {
70 final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
71
72
73
74 public Object getAttribute(Object object, String attribute) {
75 return GPathResult.this.getProperty("@" + attribute);
76 }
77 };
78
79 super.setMetaClass(newMetaClass);
80 }
81
82 public Object getProperty(final String property) {
83 if ("..".equals(property)) {
84 return parent();
85 } else if ("*".equals(property)){
86 return children();
87 } else if (property.startsWith("@")) {
88 if (property.indexOf(":") != -1) {
89 final int i = property.indexOf(":");
90
91 return new Attributes(this, "@" + property.substring(i + 1), property.substring(1, i), this.namespaceTagHints);
92 } else {
93 return new Attributes(this, property, this.namespaceTagHints);
94 }
95 } else {
96 if (property.indexOf(":") != -1) {
97 final int i = property.indexOf(":");
98
99 return new NodeChildren(this, property.substring(i + 1), property.substring(0, i), this.namespaceTagHints);
100 } else {
101 return new NodeChildren(this, property, this.namespaceTagHints);
102 }
103 }
104 }
105
106 public String name() {
107 return this.name;
108 }
109
110 public GPathResult parent() {
111 return this.parent;
112 }
113
114 public GPathResult children() {
115 return new NodeChildren(this, this.namespaceTagHints);
116 }
117
118 public String toString() {
119 return text();
120 }
121
122 public GPathResult declareNamespace(final Map newNamespaceMapping) {
123 this.namespaceMap.putAll(newNamespaceMapping);
124
125 return this;
126 }
127
128
129
130
131 public boolean equals(Object obj) {
132 return text().equals(obj.toString());
133 }
134
135 public Object getAt(final int index) {
136 final Iterator iter = iterator();
137 int count = 0;
138
139
140 while (iter.hasNext()) {
141 if (count++ == index) {
142 return iter.next();
143 } else {
144 iter.next();
145 }
146 }
147
148 throw new ArrayIndexOutOfBoundsException(index);
149 }
150
151 public List list() {
152 final Iterator iter = nodeIterator();
153 final List result = new LinkedList();
154
155 while (iter.hasNext()) {
156 result.add(iter.next());
157 }
158
159 return result;
160 }
161
162 public abstract int size();
163
164 public abstract String text();
165
166 public abstract GPathResult parents();
167
168 public abstract Iterator childNodes();
169
170 public abstract Iterator iterator();
171
172 public abstract GPathResult find(Closure closure);
173
174 public abstract GPathResult findAll(Closure closure);
175
176 public abstract Iterator nodeIterator();
177 }