1 /**
2 * JSpiff
3 * -----------------
4 * Copyright (c) 2005-2006 Emil A. Lefkof III
5 *
6 * I always give it my best shot to make a program useful and solid, but
7 * remeber that there is absolutely no warranty for using this program as
8 * stated in the following terms:
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22 package com.melloware.jspiff.jaxp;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.w3c.dom.Attr;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.EntityReference;
33 import org.w3c.dom.NamedNodeMap;
34 import org.w3c.dom.Node;
35 import org.w3c.dom.NodeList;
36 import org.w3c.dom.ProcessingInstruction;
37 import org.w3c.dom.Text;
38
39 /**
40 * RStack
41 *
42 * @since Mar. 8, 2000
43 * @version Aug. 7, 2004
44 * @author ASAMI, Tomoharu (asami@relaxer.org)
45 * @author Emil A. Lefkof III <info@melloware.com>
46 */
47 public final class RStack {
48 private Element element_;
49
50 private HashMap pi_ = new HashMap();
51
52
53
54 private HashSet consumedAttrNodes_ = null;
55
56 private HashSet consumedElementNodes_ = null;
57 private int index_;
58
59 private Object[] children_;
60
61 public RStack(Element element) {
62 element_ = element;
63 NodeList nodes = element.getChildNodes();
64 List list = new ArrayList();
65 _makeList(nodes, list);
66 int size = list.size();
67 children_ = new Object[size];
68 children_ = list.toArray(children_);
69 index_ = 0;
70 }
71
72 protected RStack() {
73 }
74
75 public Element getContextElement() {
76 return (element_);
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public Map getPIMap() {
98 return ((Map)pi_.clone());
99 }
100
101 public boolean isConsumedAttribute(Attr attr) {
102 if (consumedAttrNodes_ == null) {
103 return (false);
104 }
105 return (consumedAttrNodes_.contains(attr));
106 }
107
108 public boolean isConsumedElement(Attr attr) {
109 if (consumedElementNodes_ == null) {
110 return (false);
111 }
112 return (consumedElementNodes_.contains(attr));
113 }
114
115
116
117
118
119 public boolean isEmpty() {
120 return (index_ == children_.length);
121 }
122
123 public boolean isEmptyElement() {
124 if (index_ == children_.length) {
125 return (true);
126 }
127 for (int i = index_; i < children_.length; i++) {
128 if (children_[i] instanceof Element) {
129 return (false);
130 }
131 }
132 return (true);
133 }
134
135 public void addDirectAttributes(Map map) {
136 NamedNodeMap attrs = element_.getAttributes();
137 int size = attrs.getLength();
138 for (int i = 0; i < size; i++) {
139 Attr attr = (Attr)attrs.item(i);
140 if (!isConsumedAttribute(attr)) {
141 map.put(attr.getName(), attr.getValue());
142 }
143 }
144 }
145
146 public void consumeAttribute(Attr attr) {
147 if (attr == null) {
148 return;
149 }
150 if (consumedAttrNodes_ == null) {
151 consumedAttrNodes_ = new HashSet();
152 }
153 consumedAttrNodes_.add(attr);
154 }
155
156 public void consumeElement(Attr attr) {
157 if (consumedElementNodes_ == null) {
158 consumedElementNodes_ = new HashSet();
159 }
160 consumedElementNodes_.add(attr);
161 }
162
163 public void eat(RStack stack) {
164 element_ = stack.element_;
165 children_ = stack.children_;
166 consumedAttrNodes_ = stack.consumedAttrNodes_;
167 consumedElementNodes_ = stack.consumedElementNodes_;
168 pi_ = stack.pi_;
169 index_ = stack.index_;
170 }
171
172 public RStack makeClone() {
173 RStack newStack = new RStack();
174 newStack.element_ = element_;
175 newStack.children_ = (Object[])children_.clone();
176 if (consumedAttrNodes_ != null) {
177 newStack.consumedAttrNodes_ = (HashSet)consumedAttrNodes_.clone();
178 }
179 if (consumedElementNodes_ != null) {
180 newStack.consumedElementNodes_ = (HashSet)consumedElementNodes_.clone();
181 }
182 newStack.pi_ = (HashMap)pi_.clone();
183 newStack.index_ = index_;
184 return (newStack);
185 }
186
187 public Object peek() {
188 if (index_ == children_.length) {
189 return (null);
190 }
191 return (children_[index_]);
192 }
193
194 public Element peekElement() {
195 if (index_ == children_.length) {
196 return (null);
197 }
198 for (int i = index_; i < children_.length; i++) {
199 Object node = children_[i];
200 if (node instanceof Element) {
201 return ((Element)node);
202 }
203 }
204 return (null);
205 }
206
207 public Element[] peekElements() {
208 if (index_ == children_.length) {
209 return (null);
210 }
211 List list = new ArrayList();
212 for (int i = index_; i < children_.length; i++) {
213 Object node = children_[i];
214 if (node instanceof Element) {
215 list.add(node);
216 }
217 }
218 Element[] elements = new Element[list.size()];
219 return ((Element[])list.toArray(elements));
220 }
221
222 public Object pop() {
223 return (children_[index_++]);
224 }
225
226 public Element popElement() {
227 if (index_ == children_.length) {
228 return (null);
229 }
230 while (index_ < children_.length) {
231 Object node = children_[index_++];
232 if (node instanceof Element) {
233
234
235 return ((Element)node);
236 }
237 }
238 return (null);
239 }
240
241 public String toString() {
242 StringBuffer buffer = new StringBuffer();
243 buffer.append("[");
244 if (index_ < children_.length) {
245 Object object = children_[index_];
246 buffer.append(object);
247 for (int i = index_ + 1; i < children_.length; i++) {
248 buffer.append(",");
249 object = children_[i];
250 buffer.append(object);
251 }
252 }
253 buffer.append("]");
254 return (new String(buffer));
255 }
256
257 private void _makeList(NodeList nodes, List list) {
258 int size = nodes.getLength();
259 StringBuffer buffer = null;
260 for (int i = 0; i < size; i++) {
261 Node node = nodes.item(i);
262 if (node instanceof Element) {
263 if (buffer != null) {
264 list.add(new String(buffer));
265 buffer = null;
266 }
267 list.add(node);
268 } else if (node instanceof Text) {
269 if (buffer == null) {
270 buffer = new StringBuffer();
271 }
272 buffer.append(((Text)node).getData());
273 } else if (node instanceof ProcessingInstruction) {
274 ProcessingInstruction pi = (ProcessingInstruction)node;
275 pi_.put(pi.getTarget(), pi.getData());
276 } else if (node instanceof EntityReference) {
277 _makeList(node.getChildNodes(), list);
278 }
279 }
280 if (buffer != null) {
281 list.add(new String(buffer));
282 }
283 }
284 }