Source Code Cross Referenced for SAXalizer.java in  » Web-Framework » RSF » uk » org » ponder » saxalizer » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » RSF » uk.org.ponder.saxalizer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package uk.org.ponder.saxalizer;
002:
003:        import java.util.ArrayList;
004:        import java.util.HashMap;
005:        import java.util.Iterator;
006:        import java.util.List;
007:        import java.util.Map;
008:
009:        import org.xml.sax.AttributeList;
010:        import org.xml.sax.HandlerBase;
011:        import org.xml.sax.InputSource;
012:        import org.xml.sax.Locator;
013:        import org.xml.sax.SAXException;
014:        import org.xml.sax.SAXParseException;
015:
016:        import uk.org.ponder.arrayutil.ListUtil;
017:        import uk.org.ponder.beanutil.PropertyAccessor;
018:        import uk.org.ponder.conversion.StaticLeafParser;
019:        import uk.org.ponder.reflect.ClassGetter;
020:        import uk.org.ponder.reflect.ReflectUtils;
021:        import uk.org.ponder.reflect.ReflectiveCache;
022:        import uk.org.ponder.stringutil.CharWrap;
023:        import uk.org.ponder.util.AssertionException;
024:        import uk.org.ponder.util.CompletableDenumeration;
025:        import uk.org.ponder.util.Denumeration;
026:        import uk.org.ponder.util.EnumerationConverter;
027:        import uk.org.ponder.util.Logger;
028:        import uk.org.ponder.util.UniversalRuntimeException;
029:
030:        /**
031:         * The SAXalizer class is used to deserialize a tree of XML tags into a tree of
032:         * Java objects. Please note that this class is over 5 years old and is due for
033:         * a very major sandblasting - many comments are extremely out of date, in
034:         * addition to its using the extremely obsolete SAX1 interface. See wiki for
035:         * general comments on roadmap for this dinosaur.
036:         * <p>
037:         * Note from January '06 - this code is just getting worse and worse! More than
038:         * anything it exemplifies the all-engulphing "ball of wax" pattern where poor
039:         * design in one area simply proliferates and sucks more and more neighbouring
040:         * infrastructure down with it. Will there EVER be time to fix it... or replace
041:         * it with JiBX or comparable mature solution. Will the SAXalizer reach it's 6th
042:         * birthday alive??!
043:         * <p>
044:         * Every class that wishes to be SAXalized must implement (at least) the
045:         * interface SAXalizable, which allows the class to report the set methods it
046:         * supports for attaching subobjects to itself that correspond to XML subtags.
047:         * It may also support the interface SAXalizableAttrs in order to receive the
048:         * attributes of the XML tag it corresponds to -- if it does not, any such
049:         * attributes are thrown away.
050:         * 
051:         * Note that the class of a SAXalizing object may also implement the
052:         * DeSAXalizable interface. In this case, if an existing subobject is present
053:         * and can be delivered through the interface, SAXalizing subobjects will be
054:         * delivered onto the existing subobject rather than a new one created afresh.
055:         * 
056:         * <p>
057:         * Two "helper" base classes are called GenericSAXImpl, which allows a Java
058:         * class to store arbitary XML subtags, and SAXalizableExtraAttrs, which allows
059:         * it to store arbitrary XML attributes. Note that GenericSAXImpl itself
060:         * implements SAXalizableExtraAttrs. With these two helper classes, the line is
061:         * blurred between serializable Java objects and objects representing a DOM-like
062:         * document structure. We can even have a class which uses both styles at once;
063:         * implementing named methods for particular tags it is interested in, and
064:         * storing the rest in a "pool" of GenericSAXImpl.
065:         * 
066:         * <p>
067:         * Note that a useful modification of the standard use of SAXAccessMethodSpec to
068:         * specify a set method is to use "*" as the parameter for the set method
069:         * argument type. This will instruct the SAXalizer to use the exact tag name of
070:         * any subtags as the argument to the Class.forName() reflection method; the
071:         * class thus referenced must a) exist, and b) be a subclass of the actual
072:         * argument type of the set method specified.
073:         * 
074:         * <p>
075:         * At the bottom (err, top) of the XML tag tree we stop using the SAXalizable
076:         * interface, since there will be no further subobjects to deliver. Instead, we
077:         * use a scheme that externally encodes these object's leafiness so that we can
078:         * efficiently use primitive Java types to represent them such as String and
079:         * Date. A global registry class called SAXLeafParser stores a hashtable of
080:         * Class objects to mechanisms which can parse that type from a String. If the
081:         * SAXalizer discovers the argument type supplied through the SAXalizable
082:         * interface for a set method is registered with the SAXLeafParser, it uses that
083:         * mechanism for parsing any character data attached to the tag into a Java
084:         * object rather than continuing creating SAXalizable objects.
085:         * 
086:         * <p>
087:         * Note that any character data arriving for non--leaf nodes is currently
088:         * ignored. Should we ever do any true DOM-style parsing using the SAXalizer, a
089:         * new interface type will be required to deliver it.
090:         */
091:
092:        public class SAXalizer extends HandlerBase {
093:            private SAXalizerMappingContext mappingcontext;
094:            private StaticLeafParser leafparser;
095:
096:            public SAXalizer(SAXalizerMappingContext mappingcontext) {
097:                this .mappingcontext = mappingcontext;
098:                this .leafparser = mappingcontext.saxleafparser;
099:            }
100:
101:            /**
102:             * Sets the EntityResolverStash this SAXalizer will use to resolve entities
103:             * referred to by the XML document to be parsed.
104:             * 
105:             * @param entityresolverstash
106:             *          The required EntityResolverStash object.
107:             */
108:
109:            public void setEntityResolverStash(
110:                    EntityResolverStash entityresolverstash) {
111:                this .entityresolverstash = entityresolverstash;
112:            }
113:
114:            EntityResolverStash entityresolverstash;
115:
116:            // The ParseContext class represents everything a DocumentHandler method
117:            // needs to know about the Java object representing the currently parsing
118:            // tag. The state of the SAXalizer consists of a stack of ParseContext
119:            // objects representing the current path to the root XML tag.
120:
121:            static class ParseContext {
122:                // The object being constructed; this is created on startElement for
123:                // SAXalizable-style XML peers, but only created immediately before
124:                // calling the SAXalizable set method of the parent object in the case
125:                // of a Leaf-style XML peer. For the leaf case, this object doubles as
126:                // storage for the Class object for the leaf type.
127:                Object object;
128:                MethodAnalyser ma;
129:                // The SET method in the parent that will be used to deliver this
130:                // object when it is complete.
131:                SAXAccessMethod parentsetter;
132:                // where the parent is an array or collection, this is used to deliver
133:                // multiple children. If it is simply an enumeration, a normal setMethod
134:                // is called multiple times.
135:                // QQQQQ economise on this at some point! One hashmap created per
136:                // collection.
137:                // TODO: We THOUGHT this could be put in the child object like "objectpeer", 
138:                // but then realised that it might have been deallocated as they were popped
139:                HashMap denumerationmap;
140:                // Is this object using the GenericSAXImpl object lookup scheme
141:                boolean isgeneric;
142:                // Is this object a leaf-style object
143:                boolean isleaf;
144:                // The character data seen so far
145:                CharWrap textsofar;
146:                // The key name if this is an attribute-keyed map entry
147:                String mapkey;
148:                // Currently only set for "mappable" types, but "in general" holds the
149:                // object being constructed in the real tree.
150:                Object objectpeer;
151:
152:                ParseContext(Object object, MethodAnalyser ma,
153:                        boolean isgeneric, boolean isleaf,
154:                        SAXAccessMethod parentsetter) {
155:                    this .object = object;
156:                    this .ma = ma;
157:                    this .isgeneric = isgeneric;
158:                    this .isleaf = isleaf;
159:                    this .parentsetter = parentsetter;
160:                    textsofar = new CharWrap();
161:                }
162:
163:                public boolean hasDenumeration(String tag) {
164:                    if (denumerationmap == null) {
165:                        denumerationmap = new HashMap();
166:                    }
167:                    return (denumerationmap.get(tag) != null);
168:                }
169:
170:                public Denumeration getDenumeration(String tag) {
171:                    if (denumerationmap == null)
172:                        return null;
173:                    else
174:                        return (Denumeration) denumerationmap.get(tag);
175:                }
176:            }
177:
178:            // A stack of ParseContexts
179:            private List saxingobjects = new ArrayList();
180:
181:            // Return the Saxing object at the top of the stack.
182:            private ParseContext getSaxingObject() {
183:                return (ParseContext) ListUtil.peek(saxingobjects);
184:            }
185:
186:            /**
187:             * Blasts any parse-specific state held by this SAXalizer object, making it
188:             * ready to start a fresh parse.
189:             */
190:            public void blastState() {
191:                saxingobjects.clear();
192:            }
193:
194:            // Given a Class object, push a ParseContect object for that type onto the
195:            // saxing objects stack. If the object is a leaf type (i.e. it has no
196:            // subobjects and is
197:            // registered with the leafparser), do not actually create the required object
198:            // instance yet; instead, we store the leaf type CLASS itself!!!!
199:            // An object is either SAXalizable or a leaf type.
200:            private void pushObject(Class topush, Object oldinstance,
201:                    SAXAccessMethod parentsetter) {
202:                if (topush.isPrimitive()) {
203:                    topush = StaticLeafParser.wrapClass(topush);
204:                }
205:                boolean isgeneric = GenericSAX.class.isAssignableFrom(topush);
206:                boolean isleaf = leafparser.isLeafType(topush);
207:                // parentsetter is null for the root object only.
208:                boolean isdenumerable = parentsetter == null ? false
209:                        : parentsetter.isDenumerable();
210:                ParseContext beingparsed = getSaxingObject();
211:                // The creation of leaf objects is deferred until all their data has
212:                // arrived.
213:                Object newinstance = null;
214:                ReflectiveCache reflectivecache = mappingcontext
215:                        .getReflectiveCache();
216:                if (oldinstance == null || isdenumerable) {
217:                    if (isdenumerable
218:                            && oldinstance == null
219:                            && !beingparsed
220:                                    .hasDenumeration(parentsetter.tagname)) {
221:                        // NB, do not try to make "old" instance (collection/"peer") if we are already
222:                        // in a denumeration, since it must be the array case.
223:                        oldinstance = ReflectUtils.instantiateContainer(
224:                                parentsetter.accessclazz,
225:                                ReflectUtils.UNKNOWN_SIZE, reflectivecache);
226:                        // Do NOT deliver the object to parent now for arrays, but wait until
227:                        // enclosing tag is complete in endElement.
228:                        if (!parentsetter.accessclazz.isArray()) {
229:                            parentsetter.setChildObject(beingparsed.object,
230:                                    oldinstance);
231:                        }
232:                    }
233:                    newinstance = isleaf ? topush : reflectivecache
234:                            .construct(topush);
235:                } else
236:                    newinstance = oldinstance;
237:                MethodAnalyser ma = isleaf ? null : mappingcontext
238:                        .getAnalyser(newinstance.getClass());
239:                // "reach into the past" and note that we are now within a denumeration.
240:                // For denumerable types, oldinstance will be the previously obtained
241:                // container class, and newinstance will be of the containee type.
242:                if (isdenumerable) {
243:                    if (!beingparsed.hasDenumeration(parentsetter.tagname)) {
244:                        Denumeration den = EnumerationConverter
245:                                .getDenumeration(oldinstance, reflectivecache);
246:                        if (den == null) {
247:                            throw new UniversalRuntimeException(
248:                                    "Child "
249:                                            + oldinstance
250:                                            + " in "
251:                                            + topush
252:                                            + " cannot be made denumerable via setter with tag name "
253:                                            + parentsetter.tagname);
254:                        }
255:                        beingparsed.denumerationmap.put(parentsetter.tagname,
256:                                den);
257:                    }
258:                }
259:                saxingobjects.add(new ParseContext(newinstance, ma, isgeneric,
260:                        isleaf, parentsetter));
261:            }
262:
263:            // private CharWrap attributebuffer = new CharWrap();
264:            // Try to send the attribute list to the object on top of the stack ---
265:            // if it does not support the SAXalizableAttrs interface,
266:            // the attributes will be simply thrown away.
267:            private static void tryBlastAttrs(AttributeList attrlist,
268:                    SAXAccessMethodHash attrmethods, Object obj,
269:                    StaticLeafParser leafparser, boolean waspolymorphic,
270:                    boolean wasmap) throws SAXException {
271:                SAXalizableExtraAttrs extraattrs = obj instanceof  SAXalizableExtraAttrs ? (SAXalizableExtraAttrs) obj
272:                        : null;
273:                boolean takesextras = extraattrs != null;
274:                // use up each of the non-"extra" attributes one by one, and send any
275:                // remaining
276:                // ones into SAXalizableExtraAttrs
277:                Map extras = takesextras ? extraattrs.getAttributes() : null;
278:                boolean[] expended = takesextras ? new boolean[attrlist
279:                        .getLength()] : null;
280:
281:                for (int i = 0; i < attrlist.getLength(); ++i) {
282:                    String attrname = attrlist.getName(i);
283:                    String attrvalue = attrlist.getValue(i);
284:                    if (attrname.equals(Constants.TYPE_ATTRIBUTE_NAME)
285:                            && waspolymorphic)
286:                        continue;
287:                    if (attrname.equals(Constants.KEY_ATTRIBUTE_NAME) && wasmap)
288:                        continue;
289:                    SAXAccessMethod setattrmethod = attrmethods.get(attrname);
290:                    if (setattrmethod != null) {
291:                        if (!setattrmethod.isdevnull) {
292:                            Object newchild = leafparser.parse(
293:                                    setattrmethod.clazz, attrvalue);
294:
295:                            setattrmethod.setChildObject(obj, newchild); // invoke iiiiiit!
296:                            if (takesextras)
297:                                expended[i] = true;
298:                        }
299:                    } else if (takesextras) { // if not mapped, and it takes extras,
300:                        extras.put(attrname, attrvalue);
301:                    } else { // if all else fails, look for a default map member
302:                        // QQQQQ implement maps for main tags too.
303:                        SAXAccessMethod defaultattrmethod = attrmethods.get("");
304:                        if (defaultattrmethod == null) {
305:                            throw new UniversalRuntimeException(
306:                                    "Couldn't locate handler for attribute "
307:                                            + attrname + " in object "
308:                                            + obj.getClass());
309:                        }
310:                        Object newchild = leafparser.parse(
311:                                defaultattrmethod.clazz, attrvalue);
312:                        Map defaultmap = EnumerationConverter
313:                                .getMap(defaultattrmethod.getChildObject(obj));
314:                        defaultmap.put(attrname, newchild);
315:                    }
316:                } // end for each attribute presented by SAX
317:
318:            } // end tryBlast Attrs
319:
320:            SAXalizerCallback callback;
321:
322:            /**
323:             * Produce a subtree of objects from a SAX stream. This method produces a
324:             * subtree of objects from a SAX stream, rooted at an object of the class
325:             * specified, starting by interpreting the following SAX events as producing
326:             * an object of the type specified. It is assumed that the
327:             * <code>startElement</code> event for the root object that will be returned
328:             * has just been seen on the stream, and that all further events in the SAX
329:             * stream will be directed at this object until the matching
330:             * <code>endElement</code> event.
331:             * 
332:             * @param clazz
333:             *          Produce an object of this type.
334:             * @param attrlist
335:             *          The attribute list that was attached to the
336:             *          <code>startElement</code> tag that we just saw.
337:             * @param callback
338:             *          The caller of this method, who will receive the produced object on
339:             *          seeing of the <code>endElement</code> tag. At this point, he
340:             *          should stop forwarding <code>DocumentHandler</code> events to
341:             *          this object. This parameter may be <code>null</code>.
342:             * @exception SAXException
343:             *              If an error occured while parsing the supplied input source.
344:             */
345:            public void produceSubtree(Object rootobj, AttributeList attrlist,
346:                    SAXalizerCallback callback) throws SAXException {
347:                if (!saxingobjects.isEmpty()) {
348:                    throw new AssertionException(
349:                            "Attempt to produce new Subtree whilst another"
350:                                    + " parse was in progress");
351:                }
352:                this .callback = callback;
353:                pushObject(rootobj.getClass(), rootobj, null);
354:                // DARN, which is the correct methodanalyser?
355:                tryBlastAttrs(attrlist, getSaxingObject().ma.attrmethods,
356:                        rootobj, leafparser, false, false);
357:            }
358:
359:            /** ******* Begin methods for the DocumentHandler interface ******* */
360:
361:            public InputSource resolveEntity(String publicID, String systemID) {
362:                Logger.println("SAXalizer was asked to resolve public ID "
363:                        + publicID + " systemID " + systemID,
364:                        Logger.DEBUG_INFORMATIONAL);
365:                return entityresolverstash == null ? null : entityresolverstash
366:                        .resolve(publicID);
367:            }
368:
369:            private Locator locator;
370:
371:            public void setDocumentLocator(Locator locator) {
372:                // System.out.println("Locator received");
373:                this .locator = locator;
374:            }
375:
376:            public static String renderLocator(Locator torender) {
377:                return "line " + torender.getLineNumber() + " column "
378:                        + torender.getColumnNumber();
379:            }
380:
381:            /**
382:             * Implements the DocumentHandler interface.
383:             * 
384:             * @param tagname
385:             *          The tag name for the element just seen in the SAX stream.
386:             * @param attrlist
387:             *          The attribute list of the tag just seen in the SAX stream.
388:             * @exception SAXException
389:             *              If any exception requires to be propagated from this
390:             *              interface.
391:             */
392:            public void startElement(String tagname, AttributeList attrlist)
393:                    throws SAXException {
394:                try {
395:                    // an element has started, and we must start to construct an object to put
396:                    // it in.
397:                    // The object on top of the ParseContext stack represents the parent object
398:                    // of this object.
399:                    ParseContext beingparsed = getSaxingObject();
400:                    if (beingparsed.isleaf) {
401:                        throw new SAXParseException("Received open tag "
402:                                + tagname + " for leaf tag "
403:                                + beingparsed.parentsetter.tagname, locator);
404:                    }
405:                    SAXAccessMethodHash tagmethods = beingparsed.ma.tagmethods;
406:                    // Firstly we will look into its AccessMethodHash to see if the tagname we
407:                    // have just seen
408:                    // has been registered by the class of the parent object.
409:                    SAXAccessMethod am = tagmethods.get(tagname);
410:
411:                    Class newobjclass = null; // for some reason, idiot compiler cannot
412:                    // analyse that this is set
413:                    if (am == null) {
414:                        // if we failed to find a registered method for this tag name
415:                        try { // attempt to look up the class name now so that the forthcoming
416:                            // if statement can be nicely ordered
417:                            if (tagname.indexOf(':') == -1
418:                                    && tagname.indexOf('.') != -1)
419:                                newobjclass = Class.forName(tagname);
420:                        } catch (Exception e) {
421:                        } // exception simply indicates that the tag name is not a class
422:                        if (tagmethods.get("*") != null && newobjclass != null) {
423:                            // if the parent is polymorphic, and class name lookup succeeded, do
424:                            // nothing.
425:                            // Note, this is REALLY blank! newobjtype will be set in the try
426:                            // above.
427:                        } else if (beingparsed.object instanceof  GenericSAX) {
428:                            // but the parent is generic
429:                            newobjclass = GenericSAXImpl.class; // Child of generic will always be
430:                            // generic.
431:                        } else { // the parent is not generic
432:                            throw new SAXParseException(
433:                                    "Unexpected tag '"
434:                                            + tagname
435:                                            + "' found while parsing child of"
436:                                            + (beingparsed.object == null ? " null object"
437:                                                    : " object of "
438:                                                            + beingparsed.object
439:                                                                    .getClass()),
440:                                    locator);
441:                        }
442:                    } // end if no registered method
443:                    else {
444:                        String typeattrname = Constants.TYPE_ATTRIBUTE_NAME;
445:                        // QQQQQ genericise this somehow.
446:                        String typeattrvalue = attrlist.getValue(typeattrname);
447:                        if (am.ispolymorphic && typeattrvalue != null) {
448:                            newobjclass = mappingcontext.classnamemanager
449:                                    .findClazz(typeattrvalue);
450:                            if (newobjclass == null) {
451:                                newobjclass = ClassGetter
452:                                        .forName(typeattrvalue);
453:                            }
454:                            if (newobjclass == null) {
455:                                throw new SAXParseException(
456:                                        "Polymorphic tag "
457:                                                + tagname
458:                                                + " has \"type\" attribute with value "
459:                                                + typeattrvalue
460:                                                + " which cannot be resolved to a class ",
461:                                        locator);
462:                            }
463:                        } else {
464:                            newobjclass = am.clazz;
465:                        }
466:                    }
467:                    if (Logger.passDebugLevel(Logger.DEBUG_EXTRA_INFO)) {
468:                        Logger.println("ELEMENT CLASS determined to be "
469:                                + newobjclass);
470:                    }
471:
472:                    // if the parent is DeSAXalizable and we can find a unique non-null object
473:                    // already present at this position, use it rather than creating a new
474:                    // one.
475:                    // do not do this for leaves, since they will be replaced anyway, and in
476:                    // any
477:                    // case the existing object represents the leaf's class.
478:                    Object oldobj = null;
479:                    // enumerations and non-getters are out - we could never write to them.
480:                    // if it is a leaf type it is out, UNLESS it is a multiple in which case
481:                    // it
482:                    // is denumerable. It is ALSO out if it is "exact" since the class author
483:                    // presumably has provided a precise "add" method he wants us to use.
484:                    if (am != null
485:                            && am.canGet()
486:                            && !am.isenumonly
487:                            && (am.ismultiple || !leafparser
488:                                    .isLeafType(am.clazz)) && !am.isexactsetter) {
489:                        oldobj = am.getChildObject(beingparsed.object);
490:                        if (oldobj != null) {
491:                            // Logger.println("Acquired old object " + oldobj + " from parent "
492:                            // + beingparsed.object + " of class " + am.clazz,
493:                            // Logger.DEBUG_EXTRA_INFO);
494:                        }
495:                    }
496:                    pushObject(newobjclass, oldobj, am);
497:
498:                    ParseContext newcontext = getSaxingObject();
499:                    if (am != null && am.ismappable) {
500:                        newcontext.mapkey = attrlist
501:                                .getValue(Constants.KEY_ATTRIBUTE_NAME);
502:                        newcontext.objectpeer = am
503:                                .getChildObject(beingparsed.object);
504:                    }
505:                    if (!newcontext.isleaf) {
506:                        tryBlastAttrs(attrlist, newcontext.ma.attrmethods,
507:                                newcontext.object, leafparser,
508:                                am == null ? false : am.ispolymorphic,
509:                                am == null ? false : am.ismappable);
510:                    }
511:                } catch (Exception e) {
512:                    if (e instanceof  SAXParseException) {
513:                        throw ((SAXParseException) e);
514:                    } else {
515:                        throw UniversalRuntimeException.accumulate(e,
516:                                "Error parsing at " + renderLocator(locator));
517:                    }
518:                }
519:            }
520:
521:            /**
522:             * Implements the DocumentHandler interface.
523:             * 
524:             * @param ch
525:             *          An array holding the character data seen in the SAX stream.
526:             * @param start
527:             *          The index of the character data within the supplied array.
528:             * @param length
529:             *          The length of the character data within the supplied array.
530:             * @exception SAXException
531:             *              If any exception requires to be propagated from this
532:             *              interface.
533:             */
534:
535:            public void characters(char[] ch, int start, int length)
536:                    throws SAXException {
537:                if (saxingobjects.isEmpty()) {
538:                    throw new SAXParseException("Unexpected character data "
539:                            + new String(ch, start, length)
540:                            + " seen when there"
541:                            + " was no active object being parsed", locator);
542:                }
543:                ParseContext beingparsed = getSaxingObject();
544:                beingparsed.textsofar.append(ch, start, length);
545:                // System.err.println("CHARACTERS received at SAXALIZER:
546:                // "+beingparsed.textsofar);
547:            }
548:
549:            /**
550:             * Implements the DocumentHandler interface.
551:             * 
552:             * @param tagname
553:             *          The tag name for the element just closed in the SAX stream.
554:             * @exception SAXException
555:             *              If any exception requires to be propagated from this
556:             *              interface.
557:             */
558:
559:            public void endElement(String tagname) throws SAXException {
560:                // Logger.println("END ELEMENT received to SAXALIZER: " + tagname,
561:                // Logger.DEBUG_EXTRA_INFO);
562:                if (saxingobjects.isEmpty()) {
563:                    throw new SAXParseException(
564:                            "Unexpected closing tag for "
565:                                    + tagname
566:                                    + " seen when there was no active object being parsed",
567:                            locator);
568:                }
569:                // Our task is now to deliver the object to its parent. Firstly take
570:                // care of three special cases before finishing up.
571:                ParseContext beingparsed = getSaxingObject();
572:                SAXAccessMethod bodymethod = beingparsed.ma == null ? null
573:                        : beingparsed.ma.bodymethod;
574:
575:                AccessMethod parentsetter = beingparsed.parentsetter;
576:                // Test the special cases first, i) leaf node
577:                if (beingparsed.isleaf) {
578:                    // Leaf node objects are only created at this point
579:                    beingparsed.object = leafparser.parse(
580:                            (Class) beingparsed.object, beingparsed.textsofar
581:                                    .toString());
582:                } else if (beingparsed.isgeneric) {
583:                    // special case ii) generic parent - grab the intermediate text
584:                    // System.out.println("About to parse generic");
585:                    GenericSAX object = (GenericSAX) beingparsed.object;
586:                    object.setData(beingparsed.textsofar.toString());
587:                    object.setTag(tagname);
588:                } else if (bodymethod != null) {
589:                    // special case iii) A body method is registered to receive text
590:                    String body = beingparsed.textsofar.toString();
591:                    Object newchild = leafparser.parse(bodymethod.clazz, body);
592:                    bodymethod.setChildObject(beingparsed.object, newchild);
593:                }
594:
595:                // deal with "just destroyed" completable denumerations (array types)
596:                if (beingparsed.denumerationmap != null
597:                        && !beingparsed.denumerationmap.isEmpty()) {
598:                    for (Iterator denit = beingparsed.denumerationmap.keySet()
599:                            .iterator(); denit.hasNext();) {
600:                        String denkey = (String) denit.next();
601:                        Object denval = beingparsed.denumerationmap.get(denkey);
602:                        if (denval instanceof  CompletableDenumeration) {
603:                            Object completed = ((CompletableDenumeration) denval)
604:                                    .complete();
605:                            AccessMethod deliver = beingparsed.ma
606:                                    .getAccessMethod(denkey);
607:                            deliver.setChildObject(beingparsed.object,
608:                                    completed);
609:                        }
610:                    }
611:                }
612:
613:                ListUtil.pop(saxingobjects); // remove the completed object from the stack.
614:
615:                // Now we must try to deliver the completed object to the parent object.
616:                // if nothing left on the stack, provide the root object to our caller and
617:                // return.
618:                if (saxingobjects.isEmpty()) {
619:                    if (callback != null)
620:                        callback.productionComplete(beingparsed.object);
621:                    return;
622:                }
623:
624:                ParseContext parentcontext = getSaxingObject();
625:
626:                // Logger.println("SAXing object is " + parentcontext.object,
627:                // Logger.DEBUG_SUBATOMIC);
628:
629:                Object parentobject = parentcontext.object;
630:
631:                // Now deal with CURRENT denumerations for the just closed tag
632:                Denumeration den = null;
633:                if (parentcontext.isgeneric) {
634:                    ((GenericSAX) parentobject)
635:                            .addChild((GenericSAX) beingparsed.object);
636:                } else if ((den = parentcontext.getDenumeration(tagname)) != null) {
637:                    den.add(beingparsed.object);
638:                } else if (beingparsed.parentsetter.ismappable
639:                        && !beingparsed.parentsetter.isexactsetter) {
640:                    if (beingparsed.mapkey == null) {
641:                        throw new SAXParseException("Mappable type for tag "
642:                                + tagname + " did not supply a map key",
643:                                locator);
644:                    }
645:                    PropertyAccessor pa = MethodAnalyser.getPropertyAccessor(
646:                            beingparsed.objectpeer, mappingcontext);
647:                    pa.setProperty(beingparsed.objectpeer, beingparsed.mapkey,
648:                            beingparsed.object);
649:                } else {
650:                    parentsetter.setChildObject(parentobject,
651:                            beingparsed.object);
652:                }
653:
654:                // else if we found no set method, and parent was generic, deliver the //
655:                //object by GenericSax interface. 
656:
657:            } // end method endElement
658:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.