View Javadoc

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      // Map<String, String>
50      private HashMap pi_ = new HashMap();
51      // Set<String>
52      // private HashSet consumedAttrs_ = new HashSet();
53      // Set<Attr>
54      private HashSet consumedAttrNodes_ = null;
55      // Set<Element>
56      private HashSet consumedElementNodes_ = null;
57      private int index_;
58      // private Element lastPoppedElemnt_ = null;
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       *  public boolean hasAttributeHungry(String name) {     if (isConsumedAttribute(name)) {         return (false);
81       *  }     setCosumedAttribute(name);     return (URelaxer.hasAttribute(element_, name)); }
82       */
83  
84      /*
85       *  public boolean isConsumedAttribute(String name) {     return (consumedAttrs_.contains(name)); }
86       *
87       * public boolean isConsumedAttribute(String uri, String name) {     return (consumedAttrs_.contains(uri + "$" +
88       * name)); }
89       *
90       * public void setConsumedAttribute(String name) {     if (isConsumedAttribute(name)) {         throw (new
91       * InternalError());     }     consumedAttrs_.add(name); }
92       *
93       * public void setConsumedAttribute(String uri, String name) {     String fullname = uri + "$" + name;     if
94       * (isConsumedAttribute(fullname)) {         throw (new InternalError());     }     consumedAttrs_.add(fullname); }
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      *  public Element getLastPoppedElement() {     return (lastPoppedElemnt_); }
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                 // lastPoppedElemnt_ = (Element)node;
234                 // return (lastPoppedElemnt_);
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 }