View Javadoc

1   package org.textensor.xml;
2   
3   
4   import java.util.ArrayList;
5   import java.util.StringTokenizer;
6   
7   import org.textensor.report.E;
8   import org.textensor.stochdiff.inter.BodyValued;
9   
10  
11  public class XMLReader {
12  
13      ReflectionInstantiator instantiator;
14      int sourceLength;
15      int nerror;
16  
17      double progressFraction;
18  
19  
20      public XMLReader(ReflectionInstantiator insta) {
21          instantiator = insta;
22      }
23  
24  
25  
26  
27      public void err(String s) {
28          System.out.println(s);
29      }
30  
31  
32      public Object readObject(String s) {
33          return readFromString(s);
34      }
35  
36  
37      public Object read(String s) {
38          return readFromString(s);
39      }
40  
41  
42  
43      public Object readFromString(String s) {
44          s = XMLChecker.deGarbage(s);
45  
46          if (s == null) {
47              return null;
48          }
49  
50          progressFraction = 0.;
51  
52          nerror = 0;
53          sourceLength = (new StringTokenizer(s, "\n")).countTokens();
54  
55  
56  
57          XMLTokenizer tkz = new XMLTokenizer(s);
58  
59          XMLToken xmlt = tkz.nextToken();
60          while (xmlt.isIntro() || xmlt.isComment()) {
61  
62              if (xmlt.isComment()) {
63                  E.info("reading comment " + xmlt);
64              }
65  
66  
67              xmlt = tkz.nextToken();
68          }
69  
70  
71  
72          XMLHolder xmlHolder = new XMLHolder();
73  
74          readFieldIntoParent(tkz, xmlHolder, xmlt);
75  
76          return xmlHolder.getContent();
77      }
78  
79  
80  
81      class XMLHolder {
82  
83          Object content;
84  
85  
86          public void setContent(Object obj) {
87              content = obj;
88          }
89  
90  
91          public Object getContent() {
92              return content;
93          }
94      }
95  
96  
97  
98      public XMLToken readToken(XMLTokenizer tkz) {
99          XMLToken xmlt = tkz.nextToken();
100 
101         int lno = tkz.lineno();
102         if (nerror > 4) {
103             err("too many errors - aborting parse at line " + lno);
104 
105         }
106 
107         return xmlt;
108     }
109 
110 
111 
112     public void readFieldIntoParent(XMLTokenizer tkz, Object parent, XMLToken start) {
113 
114 
115 
116         // read the child object that is known to the parent as item.name
117         // if the parent is a vector, the object is added as a new element;
118         // if the parent is a string, the xml is just apended;
119         // otherwise the field is set.
120 
121 
122         if (!start.isOpen()) {
123             nerror++;
124             err("ERROR - read object start item was not an open tag " + start);
125             return;
126         }
127 
128 
129         Object child = null;
130 
131         if (parent instanceof String || parent instanceof StringBuffer) {
132             child = new StringBuffer();
133             ((StringBuffer)child).append(start.getOpenTagString());
134 
135         } else {
136 
137             // attributes may contain the class - the instantiator processes
138             // all the attributes here
139             Attribute[] atts = start.getAttributes();
140             child = instantiator.getChildObject(parent, start.getName(), atts);
141             if (child != null) {
142                 instantiator.applyAttributes(child, atts);
143             }
144 
145 
146             if (child == null) {
147                 child = new ArrayList();
148 
149             } else if (child instanceof String) {
150                 // in this case, set its length to 0. Subsequent parts of the
151                 // string will get appended to the current value, so want to
152                 // keep track of the fact that it is a string, without keeping
153                 // the default that may have come from above;
154                 child = new StringBuffer();
155 
156 
157             } else if (child.getClass().isArray()) {
158                 // make it an array list for the time being, then
159                 // give the list to the instantiator to make into the right sort of
160                 // array;
161                 child = new ArrayList();
162             }
163 
164 
165             if (start.isClose()) {
166                 // the tag was both an open and a close tag, so now that we've
167                 // processed the attributes, we're done;
168 
169 
170             } else {
171                 // read on and fill in fields until we get a closing tag which
172                 // matches the start tag
173                 // the fields will be inserted in target;
174 
175                 XMLToken next = readToken(tkz);
176 
177                 while (true) {
178                     if (next.isNone()) {
179                         // should mean EOF, but could also be an error
180                         // return whatever;
181                         break;
182 
183 
184                     } else if (next.isOpen()) {
185                         // open tags could mean anything - elementary field, array,
186                         // or object, but in any case, pass them back to this method;
187                         readFieldIntoParent(tkz, child, next);
188 
189 
190                     } else if (next.isClose()) {
191                         if (next.closes(start)) {
192                             // fine - close item
193 
194                             if (parent instanceof String || parent instanceof StringBuffer) {
195                                 ((StringBuffer)child).append(next.getCloseTagString());
196                             }
197 
198 
199                         } else {
200                             nerror++;
201                             E.shortError(" non-matching close item \n" + "start Item was: \n"
202                                          + start.toString() + "\n" + "but close was: \n" + next.toString() + "\n");
203                         }
204 
205                         // stop anyway - either its the right close item, or
206                         // the wrong one but lets cary on and see what happens;
207                         break;
208 
209 
210                     } else if (next.isString()) {
211                         // this occurs if we're just reading a simple string
212                         // field into the parent, or if we're in an array of strings;
213                         // first case obj is defined, so reset it;
214                         // second case put it in the vector;
215 
216 
217                         if (child instanceof ArrayList) {
218                             E.error("attempted to read string into array list?  - ignored" + next.svalue);
219 
220                             // ((ArrayList)child).add(next.svalue);
221 
222 
223                         } else if (child instanceof StringBuffer) {
224                             //   E.deprecate("xml reader - string added to string buffer " + next.svalue);
225 
226                             StringBuffer sbo = (StringBuffer)child;
227                             String ssf = sbo.toString();
228                             if (ssf.endsWith(">") || next.svalue.startsWith("<") || ssf.length() == 0) {
229                                 sbo.append(next.svalue);
230 
231                             } else {
232                                 sbo.append(" ");
233                                 sbo.append(next.svalue);
234                             }
235 
236 
237                         } else {
238                             if (child instanceof String && ((String)child).length() > 0) {
239                                 child = child + " " + next.svalue;
240 
241                                 //    E.deprecate("appended string to string " + next.svalue);
242 
243                             } else if (child == null) {
244                                 child = next.svalue;
245 
246                             }  else if (child instanceof Double && ((Double)child).doubleValue() == 0.0) {
247                                 child = new Double(next.svalue);
248 
249                                 //          E.info("resetting dbl field " + parent + " " + start.getName() + " " + next.svalue);
250 
251                             } else if (child instanceof Integer && ((Integer)child).intValue() == 0) {
252                                 child = new Integer(next.svalue);
253 
254                             } else if (child instanceof BodyValued) {
255                                 ((BodyValued)child).setBodyValue(next.svalue);
256 
257                             } else {
258                                 instantiator.appendContent(child, next.svalue);
259 
260                             }
261                         }
262 
263 
264                     } else if (next.isNumber()) {
265                         E.shortError("XMLReader sjhould never return numbers....!!!! but " + "just got " + next);
266                     }
267                     next = readToken(tkz);
268                 }
269             }
270 
271             // presumably got a close object, and have done one of:
272             // a) filled the parameters of obj;
273             // b) replaced obj with a new object of the same type
274             // c) filled the vector with strings, doubles or objects;
275 
276 
277 
278             if (child instanceof StringBuffer) {
279                 child = ((StringBuffer)child).toString();
280             }
281 
282             /*
283                      if (child instanceof ReReferencable) {
284                         ((ReReferencable)child).reReference();
285                      }
286             */
287 
288             if (parent instanceof StringBuffer) {
289                 StringBuffer psb = (StringBuffer)parent;
290                 psb.append(child);
291                 psb.append("\n");
292 
293 
294             } else if (parent instanceof XMLHolder) {
295                 ((XMLHolder)parent).setContent(child);
296 
297             } else if (parent instanceof ArrayList) {
298                 setListChild(parent, child);
299 
300             } else {
301                 instantiator.setField(parent, start.getName(), child);
302             }
303         }
304     }
305 
306 
307 
308     @SuppressWarnings( {"unchecked"})
309     private void setListChild(Object parent, Object child) {
310         ((ArrayList)parent).add(child);
311     }
312 
313 }