Source Code Cross Referenced for XMLFormat.java in  » Development » Javolution » javolution » xml » 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 » Development » Javolution » javolution.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
0003:         * Copyright (C) 2006 - Javolution (http://javolution.org/)
0004:         * All rights reserved.
0005:         * 
0006:         * Permission to use, copy, modify, and distribute this software is
0007:         * freely granted, provided that this notice is preserved.
0008:         */
0009:        package javolution.xml;
0010:
0011:        import java.util.Hashtable;
0012:        import j2me.lang.CharSequence;
0013:        import javolution.Javolution;
0014:        import javolution.text.CharArray;
0015:        import javolution.text.TextBuilder;
0016:        import javolution.text.TextFormat;
0017:        import javolution.xml.sax.Attributes;
0018:        import javolution.xml.stream.XMLStreamException;
0019:        import javolution.xml.stream.XMLStreamReader;
0020:        import javolution.xml.stream.XMLStreamReaderImpl;
0021:        import javolution.xml.stream.XMLStreamWriter;
0022:        import javolution.xml.stream.XMLStreamWriterImpl;
0023:
0024:        /**
0025:         * <p> This class represents the format base class for XML serialization and
0026:         *     deserialization.</p>
0027:         *     
0028:         * <p> Application classes typically define a default XML format for their 
0029:         *     instances using static {@link XMLFormat} class members. 
0030:         *     Formats are inherited by sub-classes. For example:[code]
0031:         *     
0032:         *     public abstract class Graphic {
0033:         *         private boolean _isVisible;
0034:         *         private Paint _paint; // null if none.
0035:         *         private Stroke _stroke; // null if none.
0036:         *         private Transform _transform; // null if none.
0037:         *          
0038:         *         // XML format with positional associations (members identified by their position),
0039:         *         // see XML package description for examples of name associations.
0040:         *         private static final XMLFormat<Graphic> XML = new XMLFormat<Graphic>(Graphic.class) {
0041:         *              public void write(Graphic g, OutputElement xml) {
0042:         *                  xml.setAttribute("isVisible", g._isVisible); 
0043:         *                  xml.add(g._paint); // First.
0044:         *                  xml.add(g._stroke); // Second.
0045:         *                  xml.add(g._transform); // Third.
0046:         *              }
0047:         *              public void read(InputElement xml, Graphic g) {
0048:         *                  g._isVisible = xml.getAttribute("isVisible", true);
0049:         *                  g._paint = xml.getNext();
0050:         *                  g._stroke = xml.getNext();
0051:         *                  g._transform = xml.getNext();
0052:         *                  return g;
0053:         *             }
0054:         *         };
0055:         *    }[/code]
0056:         *    
0057:         * <p> Due to the sequential nature of XML serialization/deserialization, 
0058:         *     formatting/parsing of XML attributes should always be performed before 
0059:         *     formatting/parsing of the XML content.</p>
0060:         * 
0061:         * <p> The mapping between classes and XML formats is defined by {@link 
0062:         *     XMLBinding} instances. 
0063:         *     Here is an example of serialization/deserialization:[code]
0064:         *     
0065:         *     // Creates a list holding diverse objects.
0066:         *     List list = new ArrayList();
0067:         *     list.add("John Doe");
0068:         *     list.add(null);
0069:         *     Map map = new FastMap();
0070:         *     map.put("ONE", new Integer(1));
0071:         *     map.put("TWO", new Integer(2));
0072:         *     list.add(map);
0073:         *     
0074:         *     // Creates some aliases to use instead of class names.
0075:         *     XMLBinding binding = new XMLBinding();
0076:         *     binding.setAlias(FastMap.class, "Map");
0077:         *     binding.setAlias(String.class, "String");
0078:         *     binding.setAlias(Integer.class, "Integer");
0079:         *     
0080:         *     // Formats the list to XML .
0081:         *     OutputStream out = new FileOutputStream("C:/list.xml");
0082:         *     XMLObjectWriter writer = new XMLObjectWriter().setOutput(out).setBinding(binding);
0083:         *     writer.write(list, "MyList", ArrayList.class);
0084:         *     writer.close();[/code]
0085:         *     
0086:         *     Here is the output <code>list.xml</code> document produced:[code]
0087:         *     
0088:         *     <MyList>
0089:         *         <String value="John Doe"/>
0090:         *         <Null/>
0091:         *         <Map>
0092:         *             <Key class="String" value="ONE"/>
0093:         *             <Value class="Integer" value="1"/>
0094:         *             <Key class="String" value="TWO"/>
0095:         *             <Value class="Integer" value="2"/>
0096:         *         </Map>
0097:         *     </MyList>[/code]
0098:         *     
0099:         *     The list can be read back with the following code:[code]
0100:         *     
0101:         *     // Reads back to a FastTable instance.
0102:         *     InputStream in = new FileInputStream("C:/list.xml");
0103:         *     XMLObjectReader reader = new XMLObjectReader().setInput(in).setBinding(binding);
0104:         *     FastTable table = reader.read("MyList", FastTable.class); 
0105:         *     reader.close();[/code]
0106:         *     </p>
0107:         *     
0108:         * <p> <i>Note:</i> Any type for which a text format is 
0109:         *    {@link TextFormat#getInstance(Class) known} can be represented as 
0110:         *    a XML attribute.</p>
0111:         * 
0112:         * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
0113:         * @version 5.1, July 4, 2007
0114:         */
0115:        public abstract class XMLFormat/*<T>*/{
0116:
0117:            /**
0118:             * Holds <code>null</code> representation.
0119:             */
0120:            private static final String NULL = "Null";
0121:
0122:            /**
0123:             * Holds the class instances.
0124:             */
0125:            static volatile XMLFormat[] _ClassInstances = new XMLFormat[64];
0126:
0127:            /**
0128:             * Holds the number of class instances.
0129:             */
0130:            static volatile int _ClassInstancesLength;
0131:
0132:            /**
0133:             * Holds the class associated to this format (static instances only).
0134:             */
0135:            final Class _class;
0136:
0137:            /**
0138:             * Creates a XML format mapped to the specified class. If the specified 
0139:             * class is <code>null</code> then the format is left unmapped ( 
0140:             * dynamic format used by custom {@link XMLBinding binding} instances).
0141:             * The static binding is unique and can only be overriden by custom
0142:             * {@link XMLBinding}. For example:[code]
0143:             *    // Overrides default binding for java.util.Collection.
0144:             *    class MyBinding extends XMLBinding {
0145:             *        XMLFormat<Collection> collectionXML = new XMLFormat<Collection>(null) { ... }; // Unmapped.
0146:             *        public XMLFormat getFormat(Class cls) {
0147:             *            if (Collection.isAssignableFrom(cls)) {
0148:             *                return collectionXML; // Overrides default XML format.
0149:             *            } else {
0150:             *                return super.getFormat(cls);
0151:             *            }
0152:             *        }
0153:             *    }[/code]
0154:             * 
0155:             * 
0156:             * @param cls the root class/interface to associate to this XML format
0157:             *        or <code>null</code> if this format is not mapped.
0158:             * @throws IllegalArgumentException if the specified class is already 
0159:             *         bound to another format.
0160:             */
0161:            protected XMLFormat(Class/*<T>*/cls) {
0162:                _class = cls;
0163:                if (cls == null)
0164:                    return; // Dynamic format.
0165:                synchronized (_ClassToFormat) {
0166:                    // Check if statically bounded.
0167:                    if (_ClassToFormat.containsKey(cls))
0168:                        throw new IllegalArgumentException(
0169:                                "Existing static binding for class "
0170:                                        + cls
0171:                                        + " can only be overriden through custom XMLBinding"
0172:                                        + " (see XMLFormat(Class) documentation)");
0173:                    final int length = XMLFormat._ClassInstancesLength;
0174:                    final XMLFormat[] formats = XMLFormat._ClassInstances;
0175:                    if (length >= formats.length) { // Resizes (ImmortalMemory).
0176:                        XMLFormat[] tmp = new XMLFormat[length * 2];
0177:                        System.arraycopy(formats, 0, tmp, 0, length);
0178:                        XMLFormat._ClassInstances = tmp;
0179:                    }
0180:                    XMLFormat._ClassInstances[XMLFormat._ClassInstancesLength++] = this ;
0181:                    _ClassToFormat.put(cls, this );
0182:                }
0183:            }
0184:
0185:            private static Hashtable _ClassToFormat = new Hashtable();
0186:
0187:            /**
0188:             * Returns the class/interface statically bound to this format or 
0189:             * <code>null</code> if none.
0190:             * 
0191:             * @return the class/interface bound to this format.
0192:             */
0193:            public final Class/*<T>*/getBoundClass() {
0194:                return _class;
0195:            }
0196:
0197:            /**
0198:             * Indicates if the object serialized through this format can be referenced
0199:             * to (default <code>true</code>). This method can be overriden to return
0200:             * <code>false</code> if  serialized objects are manipulated "by value".
0201:             *
0202:             * @return <code>true</code> if serialized object may hold a reference;
0203:             *         <code>false</code> otherwise.
0204:             * @see XMLReferenceResolver
0205:             */
0206:            public boolean isReferenceable() {
0207:                return true;
0208:            }
0209:
0210:            /**
0211:             * Allocates a new object of the specified class from the specified 
0212:             * XML input element. By default, this method returns an object created 
0213:             * using the public no-arg constructor of the specified class. 
0214:             * XML formats may override this method in order to use private/multi-arg
0215:             * constructors.  
0216:             *
0217:             * @param cls the class of the object to return.
0218:             * @param xml the XML input element.
0219:             * @return the object corresponding to the specified XML element.
0220:             */
0221:            public Object/*{T}*/newInstance(Class/*<T>*/cls, InputElement xml)
0222:                    throws XMLStreamException {
0223:                try {
0224:                    return cls.newInstance();
0225:                } catch (InstantiationException e) {
0226:                    throw new XMLStreamException(e);
0227:                } catch (IllegalAccessException e) {
0228:                    throw new XMLStreamException(e);
0229:                }
0230:            }
0231:
0232:            /**
0233:             * Formats an object into the specified XML output element.
0234:             *
0235:             * @param obj the object to format.
0236:             * @param xml the <code>XMLElement</code> destination.
0237:             */
0238:            public abstract void write(Object/*{T}*/obj, OutputElement xml)
0239:                    throws XMLStreamException;
0240:
0241:            /**
0242:             * Parses an XML input element into the specified object. 
0243:             * 
0244:             * @param xml the XML element to parse.
0245:             * @param obj the object created through {@link #newInstance}
0246:             *        and to setup from the specified XML element.
0247:             */
0248:            public abstract void read(InputElement xml, Object/*{T}*/obj)
0249:                    throws XMLStreamException;
0250:
0251:            /**
0252:             * This class represents an input XML element (unmarshalling).
0253:             */
0254:            public static final class InputElement {
0255:
0256:                /**
0257:                 * Holds the stream reader.
0258:                 */
0259:                final XMLStreamReaderImpl _reader = new XMLStreamReaderImpl();
0260:
0261:                /**
0262:                 * Holds the XML binding.
0263:                 */
0264:                private XMLBinding _binding;
0265:
0266:                /**
0267:                 * Holds the reference resolver.
0268:                 */
0269:                private XMLReferenceResolver _referenceResolver;
0270:
0271:                /**
0272:                 * Indicates if the reader is currently positioned on the next element.
0273:                 */
0274:                private boolean _isReaderAtNext;
0275:
0276:                /**
0277:                 * Default constructor.
0278:                 */
0279:                InputElement() {
0280:                    reset();
0281:                }
0282:
0283:                /**
0284:                 * Returns the StAX-like stream reader (provides complete control 
0285:                 * over the unmarshalling process).
0286:                 * 
0287:                 * @return the stream reader.
0288:                 */
0289:                public XMLStreamReader getStreamReader() {
0290:                    return _reader;
0291:                }
0292:
0293:                /**
0294:                 * Indicates if more nested XML element can be read. This method 
0295:                 * positions the {@link #getStreamReader reader} at the start of the
0296:                 * next XML element to be read (if any).
0297:                 *
0298:                 * @return <code>true</code> if there is more XML element to be read; 
0299:                 *         <code>false</code> otherwise.
0300:                 */
0301:                public boolean hasNext() throws XMLStreamException {
0302:                    if (!_isReaderAtNext) {
0303:                        _isReaderAtNext = true;
0304:                        _reader.nextTag();
0305:                    }
0306:                    return _reader.getEventType() == XMLStreamReader.START_ELEMENT;
0307:                }
0308:
0309:                /**
0310:                 * Returns the next object whose type is identified by the local name
0311:                 * and URI of the current XML element (see {@link XMLBinding}).
0312:                 *
0313:                 * @return the next nested object which can be <code>null</code>.
0314:                 * @throws XMLStreamException if <code>hasNext() == false</code>.
0315:                 */
0316:                public/*<T>*/Object/*{T}*/getNext() throws XMLStreamException {
0317:                    if (!hasNext()) // Asserts isReaderAtNext == true
0318:                        throw new XMLStreamException("No more element to read",
0319:                                _reader.getLocation());
0320:
0321:                    // Checks for null.
0322:                    if (_reader.getLocalName().equals(NULL)) {
0323:                        if (_reader.next() != XMLStreamReader.END_ELEMENT)
0324:                            throw new XMLStreamException(
0325:                                    "Non Empty Null Element");
0326:                        _isReaderAtNext = false;
0327:                        return null;
0328:                    }
0329:
0330:                    // Checks if reference.
0331:                    if (_referenceResolver != null) {
0332:                        Object obj = _referenceResolver.readReference(this );
0333:                        if (obj != null) {
0334:                            if (_reader.next() != XMLStreamReader.END_ELEMENT)
0335:                                throw new XMLStreamException(
0336:                                        "Non Empty Reference Element");
0337:                            _isReaderAtNext = false;
0338:                            return (Object/*{T}*/) obj;
0339:                        }
0340:                    }
0341:
0342:                    // Retrieves object's class.
0343:                    Class cls;
0344:                    try {
0345:                        cls = _binding.getClass(_reader.getLocalName(), _reader
0346:                                .getNamespaceURI());
0347:                    } catch (ClassNotFoundException e) {
0348:                        throw new XMLStreamException(e);
0349:                    }
0350:
0351:                    return (Object/*{T}*/) get(cls);
0352:                }
0353:
0354:                /**
0355:                 * Returns the object whose type is identified by a XML class attribute
0356:                 * only if the XML element has the specified local name.
0357:                 *
0358:                 * @param name the local name of the next element.
0359:                 * @return the next nested object or <code>null</code>.
0360:                 */
0361:                public/*<T>*/Object/*{T}*/get(String name)
0362:                        throws XMLStreamException {
0363:                    if (!hasNext()// Asserts isReaderAtNext == true
0364:                            || !_reader.getLocalName().equals(name))
0365:                        return null;
0366:
0367:                    // Checks if reference.
0368:                    if (_referenceResolver != null) {
0369:                        Object obj = _referenceResolver.readReference(this );
0370:                        if (obj != null) {
0371:                            if (_reader.next() != XMLStreamReader.END_ELEMENT)
0372:                                throw new XMLStreamException(
0373:                                        "Non Empty Reference Element");
0374:                            _isReaderAtNext = false;
0375:                            return (Object/*{T}*/) obj;
0376:                        }
0377:                    }
0378:
0379:                    // Retrieves object's class from class attribute.
0380:                    Class cls = _binding.readClassAttribute(_reader);
0381:
0382:                    return (Object/*{T}*/) get(cls);
0383:                }
0384:
0385:                /**
0386:                 * Returns the object whose type is identified by a XML class attribute
0387:                 * only if the XML element has the specified local name and URI.
0388:                 *
0389:                 * @param localName the local name.
0390:                 * @param uri the namespace URI or <code>null</code>.
0391:                 * @return the next nested object or <code>null</code>.
0392:                 */
0393:                public/*<T>*/Object/*{T}*/get(String localName, String uri)
0394:                        throws XMLStreamException {
0395:                    if (uri == null)
0396:                        return (Object/*{T}*/) get(localName);
0397:
0398:                    if (!hasNext()// Asserts isReaderAtNext == true
0399:                            || !_reader.getLocalName().equals(localName)
0400:                            || !_reader.getNamespaceURI().equals(uri))
0401:                        return null;
0402:
0403:                    // Checks if reference.
0404:                    if (_referenceResolver != null) {
0405:                        Object obj = _referenceResolver.readReference(this );
0406:                        if (obj != null) {
0407:                            if (_reader.next() != XMLStreamReader.END_ELEMENT)
0408:                                throw new XMLStreamException(
0409:                                        "Non Empty Reference Element");
0410:                            _isReaderAtNext = false;
0411:                            return (Object/*{T}*/) obj;
0412:                        }
0413:                    }
0414:
0415:                    // Retrieves object's class from class attribute.
0416:                    Class cls = _binding.readClassAttribute(_reader);
0417:
0418:                    return (Object/*{T}*/) get(cls);
0419:                }
0420:
0421:                /**
0422:                 * Returns the object of specified type only if the XML element has the
0423:                 * specified local name.
0424:                 *      
0425:                 * @param name the local name of the element to match.
0426:                 * @param cls the class identifying the format of the object to return.
0427:                 * @return the next nested object or <code>null</code>.
0428:                 */
0429:                public/*<T>*/Object/*{T}*/get(String name, Class/*<T>*/cls)
0430:                        throws XMLStreamException {
0431:                    if (!hasNext()// Asserts isReaderAtNext == true
0432:                            || !_reader.getLocalName().equals(name))
0433:                        return null;
0434:
0435:                    // Checks if reference.
0436:                    if (_referenceResolver != null) {
0437:                        Object obj = _referenceResolver.readReference(this );
0438:                        if (obj != null) {
0439:                            if (_reader.next() != XMLStreamReader.END_ELEMENT)
0440:                                throw new XMLStreamException(
0441:                                        "Non Empty Reference Element");
0442:                            _isReaderAtNext = false;
0443:                            return (Object/*{T}*/) obj;
0444:                        }
0445:                    }
0446:
0447:                    return (Object/*{T}*/) get(cls);
0448:                }
0449:
0450:                /**
0451:                 * Returns the object of specified type only if the 
0452:                 * XML element has the specified local name and namespace URI.
0453:                 *      
0454:                 * @param localName the local name.
0455:                 * @param uri the namespace URI or <code>null</code>.
0456:                 * @param cls the class identifying the format of the object to return.
0457:                 * @return the next nested object or <code>null</code>.
0458:                 */
0459:                public/*<T>*/Object/*{T}*/get(String localName, String uri,
0460:                        Class/*<T>*/cls) throws XMLStreamException {
0461:                    if (uri == null)
0462:                        return get(localName, cls);
0463:
0464:                    if (!hasNext()// Asserts isReaderAtNext == true
0465:                            || !_reader.getLocalName().equals(localName)
0466:                            || !_reader.getNamespaceURI().equals(uri))
0467:                        return null;
0468:
0469:                    // Checks if reference.
0470:                    if (_referenceResolver != null) {
0471:                        Object obj = _referenceResolver.readReference(this );
0472:                        if (obj != null) {
0473:                            if (_reader.next() != XMLStreamReader.END_ELEMENT)
0474:                                throw new XMLStreamException(
0475:                                        "Non Empty Reference Element");
0476:                            _isReaderAtNext = false;
0477:                            return (Object/*{T}*/) obj;
0478:                        }
0479:                    }
0480:
0481:                    return (Object/*{T}*/) get(cls);
0482:                }
0483:
0484:                // Builds object of specified class.
0485:                private Object get(Class cls) throws XMLStreamException {
0486:
0487:                    // Retrieves format.
0488:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0489:
0490:                    // Creates object.
0491:                    _isReaderAtNext = false; // Makes attributes accessible.
0492:                    Object obj = xmlFormat.newInstance(cls, this );
0493:
0494:                    // Adds reference (before reading to support circular reference).
0495:                    if (_referenceResolver != null) {
0496:                        _referenceResolver.createReference(obj, this );
0497:                    }
0498:
0499:                    // Parses xml.
0500:                    xmlFormat.read(this , obj);
0501:                    if (hasNext()) // Asserts _isReaderAtNext == true
0502:                        throw new XMLStreamException(
0503:                                "Incomplete element reading", _reader
0504:                                        .getLocation());
0505:                    _isReaderAtNext = false; // Skips end element.
0506:                    return obj;
0507:                }
0508:
0509:                /**
0510:                 * Returns the content of a text-only element (equivalent to 
0511:                 * {@link javolution.xml.stream.XMLStreamReader#getElementText 
0512:                 * getStreamReader().getElementText()}).
0513:                 *
0514:                 * @return the element text content or an empty sequence if none.
0515:                 */
0516:                public CharArray getText() throws XMLStreamException {
0517:                    CharArray txt = _reader.getElementText();
0518:                    _isReaderAtNext = true; // End element is next.
0519:                    return txt;
0520:                }
0521:
0522:                /**
0523:                 * Returns the attributes for this XML input element.
0524:                 *
0525:                 * @return the attributes mapping.
0526:                 */
0527:                public Attributes getAttributes() throws XMLStreamException {
0528:                    if (_isReaderAtNext)
0529:                        throw new XMLStreamException(
0530:                                "Attributes should be read before content");
0531:                    return _reader.getAttributes();
0532:                }
0533:
0534:                /**
0535:                 * Searches for the attribute having the specified name.
0536:                 *
0537:                 * @param  name the name of the attribute.
0538:                 * @return the value for the specified attribute or <code>null</code>
0539:                 *         if the attribute is not found.
0540:                 */
0541:                public CharArray getAttribute(String name)
0542:                        throws XMLStreamException {
0543:                    if (_isReaderAtNext)
0544:                        throw new XMLStreamException(
0545:                                "Attributes should be read before reading content");
0546:                    return _reader.getAttributeValue(null, toCsq(name));
0547:                }
0548:
0549:                /**
0550:                 * Returns the specified <code>String</code> attribute.
0551:                 *
0552:                 * @param  name the name of the attribute.
0553:                 * @param  defaultValue a default value.
0554:                 * @return the value for the specified attribute or
0555:                 *         the <code>defaultValue</code> if the attribute is not found.
0556:                 */
0557:                public String getAttribute(String name, String defaultValue)
0558:                        throws XMLStreamException {
0559:                    CharArray value = getAttribute(name);
0560:                    return (value != null) ? value.toString() : defaultValue;
0561:                }
0562:
0563:                /**
0564:                 * Returns the specified <code>boolean</code> attribute.
0565:                 *
0566:                 * @param  name the name of the attribute searched for.
0567:                 * @param  defaultValue the value returned if the attribute is not found.
0568:                 * @return the <code>boolean</code> value for the specified attribute or
0569:                 *         the default value if the attribute is not found.
0570:                 */
0571:                public boolean getAttribute(String name, boolean defaultValue)
0572:                        throws XMLStreamException {
0573:                    CharArray value = getAttribute(name);
0574:                    return (value != null) ? value.toBoolean() : defaultValue;
0575:                }
0576:
0577:                /**
0578:                 * Returns the specified <code>char</code> attribute.
0579:                 *
0580:                 * @param  name the name of the attribute searched for.
0581:                 * @param  defaultValue the value returned if the attribute is not found.
0582:                 * @return the <code>char</code> value for the specified attribute or
0583:                 *         the default value if the attribute is not found.
0584:                 */
0585:                public char getAttribute(String name, char defaultValue)
0586:                        throws XMLStreamException {
0587:                    CharArray value = getAttribute(name);
0588:                    if (value == null)
0589:                        return defaultValue;
0590:                    if (value.length() != 1)
0591:                        throw new XMLStreamException(
0592:                                "Single character expected (read '" + value
0593:                                        + "')");
0594:                    return value.charAt(0);
0595:                }
0596:
0597:                /**
0598:                 * Returns the specified <code>int</code> attribute. This method handles
0599:                 * string formats that are used to represent octal and hexadecimal numbers.
0600:                 *
0601:                 * @param  name the name of the attribute searched for.
0602:                 * @param  defaultValue the value returned if the attribute is not found.
0603:                 * @return the <code>int</code> value for the specified attribute or
0604:                 *         the default value if the attribute is not found.
0605:                 */
0606:                public int getAttribute(String name, int defaultValue)
0607:                        throws XMLStreamException {
0608:                    CharArray value = getAttribute(name);
0609:                    return (value != null) ? value.toInt() : defaultValue;
0610:                }
0611:
0612:                /**
0613:                 * Returns the specified <code>long</code> attribute. This method handles
0614:                 * string formats that are used to represent octal and hexadecimal numbers.
0615:                 *
0616:                 * @param  name the name of the attribute searched for.
0617:                 * @param  defaultValue the value returned if the attribute is not found.
0618:                 * @return the <code>long</code> value for the specified attribute or
0619:                 *         the default value if the attribute is not found.
0620:                 */
0621:                public long getAttribute(String name, long defaultValue)
0622:                        throws XMLStreamException {
0623:                    CharArray value = getAttribute(name);
0624:                    return (value != null) ? value.toLong() : defaultValue;
0625:                }
0626:
0627:                /**
0628:                 * Returns the specified <code>float</code> attribute.
0629:                 *
0630:                 * @param  name the name of the attribute searched for.
0631:                 * @param  defaultValue the value returned if the attribute is not found.
0632:                 * @return the <code>float</code> value for the specified attribute or
0633:                 *         the default value if the attribute is not found.
0634:                 /*@JVM-1.1+@
0635:                 public float getAttribute(String name, float defaultValue) throws XMLStreamException {
0636:                 CharArray value = getAttribute(name);
0637:                 return (value != null) ? value.toFloat() : defaultValue;
0638:                 }
0639:                 /**/
0640:
0641:                /**
0642:                 * Returns the specified <code>double</code> attribute.
0643:                 *
0644:                 * @param  name the name of the attribute searched for.
0645:                 * @param  defaultValue the value returned if the attribute is not found.
0646:                 * @return the <code>double</code> value for the specified attribute or
0647:                 *         the default value if the attribute is not found.
0648:                 /*@JVM-1.1+@
0649:                 public double getAttribute(String name, double defaultValue) throws XMLStreamException {
0650:                 CharArray value = getAttribute(name);
0651:                 return (value != null) ? value.toDouble() : defaultValue;
0652:                 }
0653:                 /**/
0654:
0655:                /**
0656:                 * Returns the attribute of same type as the specified
0657:                 * default value. The default value 
0658:                 * {@link javolution.text.TextFormat#getInstance TextFormat} is
0659:                 * used to parse the attribute value.
0660:                 *
0661:                 * @param  name the name of the attribute.
0662:                 * @param  defaultValue the value returned if the attribute is not found.
0663:                 * @return the parse value for the specified attribute or
0664:                 *         the default value if the attribute is not found.
0665:                 */
0666:                public/*<T>*/Object/*{T}*/getAttribute(String name,
0667:                        Object/*{T}*/defaultValue) throws XMLStreamException {
0668:                    CharArray value = getAttribute(name);
0669:                    if (value == null)
0670:                        return defaultValue;
0671:                    // Parses attribute value.
0672:                    Class type = defaultValue.getClass();
0673:                    TextFormat format = TextFormat.getInstance(type);
0674:                    if (format == null)
0675:                        throw new XMLStreamException(
0676:                                "No TextFormat instance for " + type);
0677:                    return (Object/*{T}*/) format.parse(value);
0678:                }
0679:
0680:                // Sets XML binding. 
0681:                void setBinding(XMLBinding xmlBinding) {
0682:                    _binding = xmlBinding;
0683:                }
0684:
0685:                // Sets XML reference resolver. 
0686:                void setReferenceResolver(
0687:                        XMLReferenceResolver xmlReferenceResolver) {
0688:                    _referenceResolver = xmlReferenceResolver;
0689:                }
0690:
0691:                // Resets for reuse.
0692:                void reset() {
0693:                    _binding = XMLBinding.DEFAULT;
0694:                    _isReaderAtNext = false;
0695:                    _reader.reset();
0696:                    _referenceResolver = null;
0697:                }
0698:            }
0699:
0700:            /**
0701:             * This class represents an output XML element (marshalling).
0702:             */
0703:            public static final class OutputElement {
0704:
0705:                /**
0706:                 * Holds the stream writer.
0707:                 */
0708:                final XMLStreamWriterImpl _writer = new XMLStreamWriterImpl();
0709:
0710:                /**
0711:                 * Holds the XML binding.
0712:                 */
0713:                private XMLBinding _binding;
0714:
0715:                /**
0716:                 * Holds the reference resolver.
0717:                 */
0718:                private XMLReferenceResolver _referenceResolver;
0719:
0720:                /**
0721:                 * Default constructor.
0722:                 */
0723:                OutputElement() {
0724:                    reset();
0725:                }
0726:
0727:                /**
0728:                 * Returns the StAX-like stream writer (provides complete control over
0729:                 * the marshalling process).
0730:                 * 
0731:                 * @return the stream writer.
0732:                 */
0733:                public XMLStreamWriter getStreamWriter() {
0734:                    return _writer;
0735:                }
0736:
0737:                /**
0738:                 * Adds the specified object or <code>null</code> as an anonymous 
0739:                 * nested element of unknown type. 
0740:                 *
0741:                 * @param obj the object added as nested element or <code>null</code>.
0742:                 */
0743:                public void add(Object obj) throws XMLStreamException {
0744:                    if (obj == null) {
0745:                        _writer.writeEmptyElement(toCsq(NULL));
0746:                        return;
0747:                    }
0748:
0749:                    // Writes start element.
0750:                    Class cls = obj.getClass();
0751:                    String localName = _binding.getLocalName(cls);
0752:                    String uri = _binding.getURI(cls);
0753:                    if (uri == null) {
0754:                        _writer.writeStartElement(toCsq(localName));
0755:                    } else {
0756:                        _writer.writeStartElement(toCsq(uri), toCsq(localName));
0757:                    }
0758:
0759:                    // Check if reference to be written.
0760:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0761:                    if ((_referenceResolver != null)
0762:                            && xmlFormat.isReferenceable()
0763:                            && _referenceResolver.writeReference(obj, this )) {
0764:                        _writer.writeEndElement();
0765:                        return; // Reference written.
0766:                    }
0767:
0768:                    xmlFormat.write(obj, this );
0769:                    _writer.writeEndElement();
0770:                }
0771:
0772:                /**
0773:                 * Adds the specified object as a named nested element of unknown type
0774:                 * (<code>null</code> objects are ignored).
0775:                 * The nested XML element contains a class attribute identifying
0776:                 * the object type.
0777:                 *
0778:                 * @param obj the object added as nested element or <code>null</code>.
0779:                 * @param name the name of the nested element.
0780:                 */
0781:                public void add(Object obj, String name)
0782:                        throws XMLStreamException {
0783:                    if (obj == null)
0784:                        return;
0785:
0786:                    // Writes start element.
0787:                    _writer.writeStartElement(toCsq(name));
0788:
0789:                    // Writes class attribute.
0790:                    Class cls = obj.getClass();
0791:                    _binding.writeClassAttribute(_writer, cls);
0792:
0793:                    // Check if reference is to be written.
0794:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0795:                    if ((_referenceResolver != null)
0796:                            && xmlFormat.isReferenceable()
0797:                            && _referenceResolver.writeReference(obj, this )) {
0798:                        _writer.writeEndElement();
0799:                        return; // Reference written.
0800:                    }
0801:
0802:                    xmlFormat.write(obj, this );
0803:                    _writer.writeEndElement();
0804:                }
0805:
0806:                /**
0807:                 * Adds the specified object as a fully qualified nested element of 
0808:                 * unknown type (<code>null</code> objects are ignored). 
0809:                 * The nested XML element contains a class attribute identifying
0810:                 * the object type.
0811:                 *
0812:                 * @param obj the object added as nested element or <code>null</code>.
0813:                 * @param localName the local name of the nested element.
0814:                 * @param uri the namespace URI of the nested element.
0815:                 */
0816:                public void add(Object obj, String localName, String uri)
0817:                        throws XMLStreamException {
0818:                    if (obj == null)
0819:                        return;
0820:
0821:                    // Writes start element.
0822:                    _writer.writeStartElement(toCsq(uri), toCsq(localName));
0823:
0824:                    // Writes class attribute.
0825:                    Class cls = obj.getClass();
0826:                    _binding.writeClassAttribute(_writer, cls);
0827:
0828:                    // Check if reference is to be written.
0829:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0830:                    if ((_referenceResolver != null)
0831:                            && xmlFormat.isReferenceable()
0832:                            && _referenceResolver.writeReference(obj, this )) {
0833:                        _writer.writeEndElement();
0834:                        return; // Reference written.
0835:                    }
0836:
0837:                    xmlFormat.write(obj, this );
0838:                    _writer.writeEndElement();
0839:                }
0840:
0841:                /**
0842:                 * Adds the specified object as a named nested element of specified  
0843:                 * actual type (<code>null</code> objects are ignored).
0844:                 * The nested XML element does not contain any class attribute.
0845:                 *
0846:                 * @param obj the object added as nested element or <code>null</code>.
0847:                 * @param name the name of the nested element.
0848:                 * @param cls the class identifying the format of the specified object.
0849:                 */
0850:                public/*<T>*/void add(Object/*{T}*/obj, String name,
0851:                        Class/*<T>*/cls) throws XMLStreamException {
0852:                    if (obj == null)
0853:                        return;
0854:
0855:                    // Writes start element.
0856:                    _writer.writeStartElement(toCsq(name));
0857:
0858:                    // Check if reference is to be written.
0859:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0860:                    if ((_referenceResolver != null)
0861:                            && xmlFormat.isReferenceable()
0862:                            && _referenceResolver.writeReference(obj, this )) {
0863:                        _writer.writeEndElement();
0864:                        return; // Reference written.
0865:                    }
0866:
0867:                    xmlFormat.write(obj, this );
0868:                    _writer.writeEndElement();
0869:                }
0870:
0871:                /**
0872:                 * Adds the specified object as a fully qualified nested element of
0873:                 * specified actual type (<code>null</code> objects are ignored). 
0874:                 * The nested XML element does not contain any class attribute.
0875:                 *
0876:                 * @param obj the object added as nested element or <code>null</code>.
0877:                 * @param localName the local name of the nested element.
0878:                 * @param uri the namespace URI of the nested element.
0879:                 * @param cls the class identifying the format of the specified object.
0880:                 */
0881:                public/*<T>*/void add(Object/*{T}*/obj, String localName,
0882:                        String uri, Class/*<T>*/cls) throws XMLStreamException {
0883:                    if (obj == null)
0884:                        return;
0885:
0886:                    // Writes start element.
0887:                    _writer.writeStartElement(toCsq(uri), toCsq(localName));
0888:
0889:                    // Check if reference is to be written.
0890:                    XMLFormat xmlFormat = _binding.getFormat(cls);
0891:                    if ((_referenceResolver != null)
0892:                            && xmlFormat.isReferenceable()
0893:                            && _referenceResolver.writeReference(obj, this )) {
0894:                        _writer.writeEndElement();
0895:                        return; // Reference written.
0896:                    }
0897:
0898:                    xmlFormat.write(obj, this );
0899:                    _writer.writeEndElement();
0900:                }
0901:
0902:                /**
0903:                 * Adds the content of a text-only element (equivalent to {@link 
0904:                 * javolution.xml.stream.XMLStreamWriter#writeCharacters(CharSequence) 
0905:                 * getStreamWriter().writeCharacters(text)}).
0906:                 *
0907:                 * @param text the element text content or an empty sequence if none.
0908:                 */
0909:                public void addText(CharSequence text)
0910:                        throws XMLStreamException {
0911:                    _writer.writeCharacters(text);
0912:                }
0913:
0914:                /**
0915:                 * Equivalent to {@link #addText(CharSequence)} 
0916:                 * (for J2ME compatibility).
0917:                 *
0918:                 * @param text the element text content or an empty sequence if none.
0919:                 */
0920:                public void addText(String text) throws XMLStreamException {
0921:                    _writer.writeCharacters(toCsq(text));
0922:                }
0923:
0924:                /**
0925:                 * Sets the specified <code>CharSequence</code> attribute
0926:                 * (<code>null</code> values are ignored).
0927:                 *
0928:                 * @param  name the attribute name.
0929:                 * @param  value the attribute value or <code>null</code>.
0930:                 */
0931:                public void setAttribute(String name, CharSequence value)
0932:                        throws XMLStreamException {
0933:                    if (value == null)
0934:                        return;
0935:                    _writer.writeAttribute(toCsq(name), value);
0936:                }
0937:
0938:                /**
0939:                 * Sets the specified <code>String</code> attribute
0940:                 * (<code>null</code> values are ignored).
0941:                 *
0942:                 * @param  name the attribute name.
0943:                 * @param  value the attribute value.
0944:                 */
0945:                public void setAttribute(String name, String value)
0946:                        throws XMLStreamException {
0947:                    if (value == null)
0948:                        return;
0949:                    _writer.writeAttribute(toCsq(name), toCsq(value));
0950:                }
0951:
0952:                /**
0953:                 * Sets the specified <code>boolean</code> attribute.
0954:                 * 
0955:                 * @param  name the attribute name.
0956:                 * @param  value the <code>boolean</code> value for the specified attribute.
0957:                 */
0958:                public void setAttribute(String name, boolean value)
0959:                        throws XMLStreamException {
0960:                    setAttribute(name, _tmpTextBuilder.clear().append(value));
0961:                }
0962:
0963:                private TextBuilder _tmpTextBuilder = new TextBuilder();
0964:
0965:                /**
0966:                 * Sets the specified <code>char</code> attribute.
0967:                 * 
0968:                 * @param  name the attribute name.
0969:                 * @param  value the <code>char</code> value for the specified attribute.
0970:                 */
0971:                public void setAttribute(String name, char value)
0972:                        throws XMLStreamException {
0973:                    setAttribute(name, (TextBuilder) _tmpTextBuilder.clear()
0974:                            .append(value));
0975:                }
0976:
0977:                /**
0978:                 * Sets the specified <code>int</code> attribute.
0979:                 * 
0980:                 * @param  name the attribute name.
0981:                 * @param  value the <code>int</code> value for the specified attribute.
0982:                 */
0983:                public void setAttribute(String name, int value)
0984:                        throws XMLStreamException {
0985:                    setAttribute(name, _tmpTextBuilder.clear().append(value));
0986:                }
0987:
0988:                /**
0989:                 * Sets the specified <code>long</code> attribute.
0990:                 * 
0991:                 * @param  name the attribute name.
0992:                 * @param  value the <code>long</code> value for the specified attribute.
0993:                 */
0994:                public void setAttribute(String name, long value)
0995:                        throws XMLStreamException {
0996:                    setAttribute(name, _tmpTextBuilder.clear().append(value));
0997:                }
0998:
0999:                /**
1000:                 * Sets the specified <code>float</code> attribute.
1001:                 * 
1002:                 * @param  name the attribute name.
1003:                 * @param  value the <code>float</code> value for the specified attribute.
1004:                 /*@JVM-1.1+@
1005:                 public void setAttribute(String name, float value) throws XMLStreamException {
1006:                 setAttribute(name, _tmpTextBuilder.clear().append(value));
1007:                 }
1008:                 /**/
1009:
1010:                /**
1011:                 * Sets the specified <code>double</code> attribute.
1012:                 * 
1013:                 * @param  name the attribute name.
1014:                 * @param  value the <code>double</code> value for the specified attribute.
1015:                 /*@JVM-1.1+@
1016:                 public void setAttribute(String name, double value) throws XMLStreamException {
1017:                 setAttribute(name, _tmpTextBuilder.clear().append(value));
1018:                 }
1019:                 /**/
1020:
1021:                /**
1022:                 * Sets the specified attribute using its associated 
1023:                 * {@link javolution.text.TextFormat#getInstance TextFormat}.
1024:                 * 
1025:                 * @param  name the name of the attribute.
1026:                 * @param  value the <code>Boolean</code> value for the specified attribute
1027:                 *         or <code>null</code> in which case the attribute is not set.
1028:                 */
1029:                public void setAttribute(String name, Object value)
1030:                        throws XMLStreamException {
1031:                    if (value == null)
1032:                        return;
1033:                    Class type = value.getClass();
1034:                    TextFormat format = TextFormat.getInstance(type);
1035:                    if (format == null)
1036:                        throw new XMLStreamException(
1037:                                "No TextFormat instance for " + type);
1038:                    setAttribute(name, (TextBuilder) format.format(value,
1039:                            _tmpTextBuilder.clear()));
1040:                }
1041:
1042:                // Sets XML binding. 
1043:                void setBinding(XMLBinding xmlBinding) {
1044:                    _binding = xmlBinding;
1045:                }
1046:
1047:                // Sets XML reference resolver. 
1048:                void setReferenceResolver(
1049:                        XMLReferenceResolver xmlReferenceResolver) {
1050:                    _referenceResolver = xmlReferenceResolver;
1051:                }
1052:
1053:                // Resets for reuse.
1054:                void reset() {
1055:                    _binding = XMLBinding.DEFAULT;
1056:                    _writer.reset();
1057:                    _writer.setRepairingNamespaces(true);
1058:                    _writer.setAutomaticEmptyElements(true);
1059:                    _referenceResolver = null;
1060:                }
1061:
1062:            }
1063:
1064:            private static CharSequence toCsq/**/(Object str) {
1065:                return Javolution.j2meToCharSeq(str);
1066:            }
1067:
1068:            /**
1069:             * Creates an unmapped XML format.
1070:             * 
1071:             * @deprecated <code>XMLFormat(null) should be used instead.
1072:             */
1073:            protected XMLFormat() {
1074:                this(null);
1075:            }
1076:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.