Source Code Cross Referenced for XMLSerialization.java in  » Science » weka » weka » core » 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 » Science » weka » weka.core.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *    This program is free software; you can redistribute it and/or modify
0003:         *    it under the terms of the GNU General Public License as published by
0004:         *    the Free Software Foundation; either version 2 of the License, or
0005:         *    (at your option) any later version.
0006:         *
0007:         *    This program is distributed in the hope that it will be useful,
0008:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0009:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0010:         *    GNU General Public License for more details.
0011:         *
0012:         *    You should have received a copy of the GNU General Public License
0013:         *    along with this program; if not, write to the Free Software
0014:         *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0015:         */
0016:
0017:        /*
0018:         * XMLSerialization.java
0019:         * Copyright (C) 2004 University of Waikato, Hamilton, New Zealand
0020:         *
0021:         */
0022:
0023:        package weka.core.xml;
0024:
0025:        import weka.core.Utils;
0026:        import weka.core.Version;
0027:
0028:        import java.beans.BeanInfo;
0029:        import java.beans.Introspector;
0030:        import java.beans.PropertyDescriptor;
0031:        import java.io.BufferedInputStream;
0032:        import java.io.BufferedOutputStream;
0033:        import java.io.File;
0034:        import java.io.FileInputStream;
0035:        import java.io.FileOutputStream;
0036:        import java.io.InputStream;
0037:        import java.io.ObjectInputStream;
0038:        import java.io.ObjectOutputStream;
0039:        import java.io.OutputStream;
0040:        import java.io.Reader;
0041:        import java.io.Writer;
0042:        import java.lang.reflect.Array;
0043:        import java.lang.reflect.Constructor;
0044:        import java.lang.reflect.Method;
0045:        import java.util.Enumeration;
0046:        import java.util.Hashtable;
0047:        import java.util.Vector;
0048:
0049:        import org.w3c.dom.Document;
0050:        import org.w3c.dom.Element;
0051:
0052:        /**
0053:         * With this class objects can be serialized to XML instead into a binary 
0054:         * format. It uses introspection (cf. beans) to retrieve the data from the
0055:         * given object, i.e. it can only access beans-conform fields automatically.
0056:         * <p>
0057:         * The generic approach of writing data as XML can be overriden by adding 
0058:         * custom methods for reading/writing in a derived class
0059:         * (cf. <code>m_Properties</code>, <code>m_CustomMethods</code>).<br>
0060:         * Custom read and write methods must have the same signature (and also be 
0061:         * <code>public</code>!) as the <code>readFromXML</code> and <code>writeToXML</code>
0062:         * methods. Methods that apply to the naming rule <code>read + property name</code>
0063:         * are added automatically to the list of methods by the method 
0064:         * <code>XMLSerializationMethodHandler.addMethods(...)</code>.  
0065:         * <p>
0066:         * Other properties that are not conform the bean set/get-methods have to be 
0067:         * processed manually in a derived class (cf. <code>readPostProcess(Object)</code>, 
0068:         * <code>writePostProcess(Object)</code>).
0069:         * <p>
0070:         * For a complete XML serialization/deserialization have a look at the 
0071:         * <code>KOML</code> class.
0072:         * <p>
0073:         * If a stored class has a constructor that takes a String to initialize
0074:         * (e.g. String or Double) then the content of the tag will used for the
0075:         * constructor, e.g. from 
0076:         * <pre>&lt;object name="name" class="String" primitive="no"&gt;Smith&lt;/object&gt;</pre>
0077:         * "Smith" will be used to instantiate a String object as constructor argument.
0078:         * <p>   
0079:         * 
0080:         * @see KOML
0081:         * @see #fromXML(Document)
0082:         * @see #toXML(Object)
0083:         * @see #m_Properties
0084:         * @see #m_CustomMethods
0085:         * @see #readPostProcess(Object)
0086:         * @see #writePostProcess(Object)
0087:         * @see #readFromXML(Element)
0088:         * @see #writeToXML(Element, Object, String)
0089:         * 
0090:         * @author FracPete (fracpete at waikato dot ac dot nz)
0091:         * @version $Revision: 1.15 $ 
0092:         */
0093:        public class XMLSerialization {
0094:            /** for debugging purposes only */
0095:            protected static boolean DEBUG = false;
0096:
0097:            /** the node that is currently processed, in case of writing the parent node
0098:             * (something might go wrong writing the new child) and in case of reading 
0099:             * the actual node that is tried to process */
0100:            protected Element m_CurrentNode = null;
0101:
0102:            /** the tag for an object */
0103:            public final static String TAG_OBJECT = "object";
0104:
0105:            /** the version attribute */
0106:            public final static String ATT_VERSION = XMLDocument.ATT_VERSION;
0107:
0108:            /** the tag for the name */
0109:            public final static String ATT_NAME = XMLDocument.ATT_NAME;
0110:
0111:            /** the tag for the class */
0112:            public final static String ATT_CLASS = "class";
0113:
0114:            /** the tag whether primitive or not (yes/no) */
0115:            public final static String ATT_PRIMITIVE = "primitive";
0116:
0117:            /** the tag whether array or not (yes/no) */
0118:            public final static String ATT_ARRAY = "array";
0119:
0120:            /** the tag whether null or not (yes/no) */
0121:            public final static String ATT_NULL = "null";
0122:
0123:            /** the value "yes" for the primitive and array attribute */
0124:            public final static String VAL_YES = XMLDocument.VAL_YES;
0125:
0126:            /** the value "no" for the primitive and array attribute */
0127:            public final static String VAL_NO = XMLDocument.VAL_NO;
0128:
0129:            /** the value of the name for the root node */
0130:            public final static String VAL_ROOT = "__root__";
0131:
0132:            /** the root node of the XML document */
0133:            public final static String ROOT_NODE = TAG_OBJECT;
0134:
0135:            /** default value for attribute ATT_PRIMITIVE
0136:             * @see #ATT_PRIMITIVE */
0137:            public final static String ATT_PRIMITIVE_DEFAULT = VAL_NO;
0138:
0139:            /** default value for attribute ATT_ARRAY
0140:             * @see #ATT_ARRAY */
0141:            public final static String ATT_ARRAY_DEFAULT = VAL_NO;
0142:
0143:            /** default value for attribute ATT_NULL
0144:             * @see #ATT_NULL */
0145:            public final static String ATT_NULL_DEFAULT = VAL_NO;
0146:
0147:            /** the DOCTYPE for the serialization */
0148:            public final static String DOCTYPE = "<!"
0149:                    + XMLDocument.DTD_DOCTYPE
0150:                    + " "
0151:                    + ROOT_NODE
0152:                    + "\n"
0153:                    + "[\n"
0154:                    + "   <!"
0155:                    + XMLDocument.DTD_ELEMENT
0156:                    + " "
0157:                    + TAG_OBJECT
0158:                    + " ("
0159:                    + XMLDocument.DTD_PCDATA
0160:                    + XMLDocument.DTD_SEPARATOR
0161:                    + TAG_OBJECT
0162:                    + ")"
0163:                    + XMLDocument.DTD_ZERO_OR_MORE
0164:                    + ">\n"
0165:                    + "   <!"
0166:                    + XMLDocument.DTD_ATTLIST
0167:                    + " "
0168:                    + TAG_OBJECT
0169:                    + " "
0170:                    + ATT_NAME
0171:                    + "      "
0172:                    + XMLDocument.DTD_CDATA
0173:                    + " "
0174:                    + XMLDocument.DTD_REQUIRED
0175:                    + ">\n"
0176:                    + "   <!"
0177:                    + XMLDocument.DTD_ATTLIST
0178:                    + " "
0179:                    + TAG_OBJECT
0180:                    + " "
0181:                    + ATT_CLASS
0182:                    + "     "
0183:                    + XMLDocument.DTD_CDATA
0184:                    + " "
0185:                    + XMLDocument.DTD_REQUIRED
0186:                    + ">\n"
0187:                    + "   <!"
0188:                    + XMLDocument.DTD_ATTLIST
0189:                    + " "
0190:                    + TAG_OBJECT
0191:                    + " "
0192:                    + ATT_PRIMITIVE
0193:                    + " "
0194:                    + XMLDocument.DTD_CDATA
0195:                    + " \""
0196:                    + ATT_PRIMITIVE_DEFAULT
0197:                    + "\">\n"
0198:                    + "   <!"
0199:                    + XMLDocument.DTD_ATTLIST
0200:                    + " "
0201:                    + TAG_OBJECT
0202:                    + " "
0203:                    + ATT_ARRAY
0204:                    + "     "
0205:                    + XMLDocument.DTD_CDATA
0206:                    + " \""
0207:                    + ATT_ARRAY_DEFAULT
0208:                    + "\">   <!-- the dimensions of the array; no=0, yes=1 -->\n"
0209:                    + "   <!" + XMLDocument.DTD_ATTLIST + " " + TAG_OBJECT
0210:                    + " " + ATT_NULL + "      " + XMLDocument.DTD_CDATA + " \""
0211:                    + ATT_NULL_DEFAULT + "\">\n" + "   <!"
0212:                    + XMLDocument.DTD_ATTLIST + " " + TAG_OBJECT + " "
0213:                    + ATT_VERSION + "   " + XMLDocument.DTD_CDATA + " \""
0214:                    + Version.VERSION + "\">\n" + "]\n" + ">";
0215:
0216:            /** the XMLDocument that performs the transformation to and fro XML */
0217:            protected XMLDocument m_Document = null;
0218:
0219:            /** for handling properties (ignored/allowed) */
0220:            protected PropertyHandler m_Properties = null;
0221:
0222:            /** for handling custom read/write methods */
0223:            protected XMLSerializationMethodHandler m_CustomMethods = null;
0224:
0225:            /** for overriding class names (Class &lt;-&gt; Classname (String)) 
0226:             * @see #overrideClassname(Object) */
0227:            protected Hashtable m_ClassnameOverride = null;
0228:
0229:            /**
0230:             * initializes the serialization
0231:             * 
0232:             * @throws Exception if initialization fails
0233:             */
0234:            public XMLSerialization() throws Exception {
0235:                super ();
0236:                clear();
0237:            }
0238:
0239:            /**
0240:             * used for debugging purposes, i.e. only if DEBUG is set to true.
0241:             * needs a newly generated Throwable instance to get the method/line from
0242:             * @param t      a throwable instance, generated in the calling method
0243:             * @param msg    a message to pring
0244:             * @see          #DEBUG
0245:             */
0246:            protected void trace(Throwable t, String msg) {
0247:                if ((DEBUG) && (t.getStackTrace().length > 0)) {
0248:                    System.out.println("trace: " + t.getStackTrace()[0] + ": "
0249:                            + msg);
0250:                }
0251:            }
0252:
0253:            /**
0254:             * generates internally a new XML document and clears also the IgnoreList and
0255:             * the mappings for the Read/Write-Methods
0256:             * 
0257:             * @throws Exception	if something goes wrong
0258:             */
0259:            public void clear() throws Exception {
0260:                m_Document = new XMLDocument();
0261:                m_Document.setValidating(true);
0262:                m_Document.newDocument(DOCTYPE, ROOT_NODE);
0263:
0264:                m_Properties = new PropertyHandler();
0265:                m_CustomMethods = new XMLSerializationMethodHandler(this );
0266:
0267:                m_ClassnameOverride = new Hashtable();
0268:                // java.io.File is sometimes represented as another class:
0269:                // - Win32: sun.awt.shell.Win32ShellFolder2 
0270:                // - Linux: sun.awt.shell.DefaultShellFolder
0271:                // -> we set it to "java.io.File"
0272:                m_ClassnameOverride.put(java.io.File.class, java.io.File.class
0273:                        .getName());
0274:
0275:                setVersion(Version.VERSION);
0276:
0277:                m_CurrentNode = null;
0278:            }
0279:
0280:            /**
0281:             * sets the given version string in the XML document
0282:             * 
0283:             * @param version	the new version string
0284:             */
0285:            private void setVersion(String version) {
0286:                Document doc;
0287:
0288:                doc = m_Document.getDocument();
0289:                doc.getDocumentElement().setAttribute(ATT_VERSION, version);
0290:            }
0291:
0292:            /**
0293:             * returns the WEKA version with which the serialized object was created
0294:             * 
0295:             * @return		the current version
0296:             * @see Version 
0297:             */
0298:            public String getVersion() {
0299:                Document doc;
0300:                String result;
0301:
0302:                doc = m_Document.getDocument();
0303:                result = doc.getDocumentElement().getAttribute(ATT_VERSION);
0304:
0305:                return result;
0306:            }
0307:
0308:            /**
0309:             * Checks the version in the current Document with the one of the current
0310:             * release. If the version differ, a warning is printed.
0311:             */
0312:            private void checkVersion() {
0313:                String versionStr;
0314:                Version version;
0315:
0316:                version = new Version();
0317:                versionStr = getVersion();
0318:                if (versionStr.equals(""))
0319:                    System.out.println("WARNING: has no version!");
0320:                else if (version.isOlder(versionStr))
0321:                    System.out.println("WARNING: loading a newer version ("
0322:                            + versionStr + " > " + Version.VERSION + ")!");
0323:                else if (version.isNewer(versionStr))
0324:                    System.out.println("NOTE: loading an older version ("
0325:                            + versionStr + " < " + Version.VERSION + ")!");
0326:            }
0327:
0328:            /**
0329:             * returns a hashtable with PropertyDescriptors that have "get" and "set" 
0330:             * methods indexed by the property name.
0331:             * 
0332:             * @see java.beans.PropertyDescriptor
0333:             * @param o the object to retrieve the descriptors from
0334:             * @return the PropertyDescriptors indexed by name of the property
0335:             * @throws Exception if the introspection fails
0336:             */
0337:            protected Hashtable getDescriptors(Object o) throws Exception {
0338:                BeanInfo info;
0339:                PropertyDescriptor[] desc;
0340:                int i;
0341:                Hashtable result;
0342:
0343:                result = new Hashtable();
0344:
0345:                info = Introspector.getBeanInfo(o.getClass());
0346:                desc = info.getPropertyDescriptors();
0347:                for (i = 0; i < desc.length; i++) {
0348:                    // get AND set method?
0349:                    if ((desc[i].getReadMethod() != null)
0350:                            && (desc[i].getWriteMethod() != null)) {
0351:                        // in ignore list, i.e. a general ignore without complete path?
0352:                        if (m_Properties.isIgnored(desc[i].getDisplayName()))
0353:                            continue;
0354:
0355:                        // in ignore list of the class?
0356:                        if (m_Properties.isIgnored(o, desc[i].getDisplayName()))
0357:                            continue;
0358:
0359:                        // not an allowed property
0360:                        if (!m_Properties
0361:                                .isAllowed(o, desc[i].getDisplayName()))
0362:                            continue;
0363:
0364:                        result.put(desc[i].getDisplayName(), desc[i]);
0365:                    }
0366:                }
0367:
0368:                return result;
0369:            }
0370:
0371:            /**
0372:             * returns the path of the "name" attribute from the root down to this node
0373:             * (including it).
0374:             * 
0375:             * @param node the node to get the path for
0376:             * @return the complete "name" path of this node
0377:             */
0378:            protected String getPath(Element node) {
0379:                String result;
0380:
0381:                result = node.getAttribute(ATT_NAME);
0382:
0383:                while (node.getParentNode() != node.getOwnerDocument()) {
0384:                    node = (Element) node.getParentNode();
0385:                    result = node.getAttribute(ATT_NAME) + "." + result;
0386:                }
0387:
0388:                return result;
0389:            }
0390:
0391:            /**
0392:             * returns either <code>VAL_YES</code> or <code>VAL_NO</code> depending 
0393:             * on the value of <code>b</code>
0394:             * 
0395:             * @param b the boolean to turn into a string
0396:             * @return the value in string representation
0397:             */
0398:            protected String booleanToString(boolean b) {
0399:                if (b)
0400:                    return VAL_YES;
0401:                else
0402:                    return VAL_NO;
0403:            }
0404:
0405:            /**
0406:             * turns the given string into a boolean, if a positive number is given, 
0407:             * then zero is considered FALSE, every other number TRUE; the empty string 
0408:             * is also considered being FALSE
0409:             * 
0410:             * @param s the string to turn into a boolean
0411:             * @return the string as boolean
0412:             */
0413:            protected boolean stringToBoolean(String s) {
0414:                if (s.equals(""))
0415:                    return false;
0416:                else if (s.equals(VAL_YES))
0417:                    return true;
0418:                else if (s.equalsIgnoreCase("true"))
0419:                    return true;
0420:                else if (s.replaceAll("[0-9]*", "").equals(""))
0421:                    return (Integer.parseInt(s) != 0);
0422:                else
0423:                    return false;
0424:            }
0425:
0426:            /**
0427:             * appends a new node to the parent with the given parameters (a non-array)
0428:             * 
0429:             * @param parent the parent of this node. if it is <code>null</code> the 
0430:             *        document root element is used
0431:             * @param name the name of the node
0432:             * @param classname the classname for this node
0433:             * @param primitive whether it is a primitve data type or not (i.e. an object)
0434:             * @return the generated node 
0435:             */
0436:            protected Element addElement(Element parent, String name,
0437:                    String classname, boolean primitive) {
0438:                return addElement(parent, name, classname, primitive, 0);
0439:            }
0440:
0441:            /**
0442:             * appends a new node to the parent with the given parameters
0443:             * 
0444:             * @param parent the parent of this node. if it is <code>null</code> the 
0445:             *        document root element is used
0446:             * @param name the name of the node
0447:             * @param classname the classname for this node
0448:             * @param primitive whether it is a primitve data type or not (i.e. an object)
0449:             * @param array the dimensions of the array (0 if not an array)
0450:             * @return the generated node 
0451:             */
0452:            protected Element addElement(Element parent, String name,
0453:                    String classname, boolean primitive, int array) {
0454:                return addElement(parent, name, classname, primitive, array,
0455:                        false);
0456:            }
0457:
0458:            /**
0459:             * appends a new node to the parent with the given parameters
0460:             * 
0461:             * @param parent the parent of this node. if it is <code>null</code> the 
0462:             *        document root element is used
0463:             * @param name the name of the node
0464:             * @param classname the classname for this node
0465:             * @param primitive whether it is a primitve data type or not (i.e. an object)
0466:             * @param array the dimensions of the array (0 if not an array)
0467:             * @param isnull whether it is null
0468:             * @return the generated node 
0469:             */
0470:            protected Element addElement(Element parent, String name,
0471:                    String classname, boolean primitive, int array,
0472:                    boolean isnull) {
0473:                Element result;
0474:
0475:                if (parent == null)
0476:                    result = m_Document.getDocument().getDocumentElement();
0477:                else
0478:                    result = (Element) parent.appendChild(m_Document
0479:                            .getDocument().createElement(TAG_OBJECT));
0480:
0481:                // attributes
0482:                // mandatory attributes:
0483:                result.setAttribute(ATT_NAME, name);
0484:                result.setAttribute(ATT_CLASS, classname);
0485:
0486:                // add following attributes only if necessary, i.e., different from default:
0487:                if (!booleanToString(primitive).equals(ATT_PRIMITIVE_DEFAULT))
0488:                    result.setAttribute(ATT_PRIMITIVE,
0489:                            booleanToString(primitive));
0490:
0491:                // multi-dimensional array?
0492:                if (array > 1) {
0493:                    result.setAttribute(ATT_ARRAY, Integer.toString(array));
0494:                }
0495:                // backwards compatible: 0 -> no array ("no"), 1 -> 1-dim. array ("yes")
0496:                else {
0497:                    if (!booleanToString(array == 1).equals(ATT_ARRAY_DEFAULT))
0498:                        result.setAttribute(ATT_ARRAY,
0499:                                booleanToString(array == 1));
0500:                }
0501:
0502:                if (!booleanToString(isnull).equals(ATT_NULL_DEFAULT))
0503:                    result.setAttribute(ATT_NULL, booleanToString(isnull));
0504:
0505:                return result;
0506:            }
0507:
0508:            /**
0509:             * if the class of the given object (or one of its ancestors) is stored in 
0510:             * the classname override hashtable, then the override name is returned 
0511:             * otherwise the classname of the given object.
0512:             * 
0513:             * @param o          the object to check for overriding its classname
0514:             * @return           if overridden then the classname stored in the hashtable,
0515:             *                   otherwise the classname of the given object
0516:             * @see              #m_ClassnameOverride
0517:             */
0518:            protected String overrideClassname(Object o) {
0519:                Enumeration enm;
0520:                String result;
0521:                Class currentCls;
0522:
0523:                result = o.getClass().getName();
0524:
0525:                // check overrides
0526:                enm = m_ClassnameOverride.keys();
0527:                while (enm.hasMoreElements()) {
0528:                    currentCls = (Class) enm.nextElement();
0529:                    if (currentCls.isInstance(o)) {
0530:                        result = (String) m_ClassnameOverride.get(currentCls);
0531:                        break;
0532:                    }
0533:                }
0534:
0535:                return result;
0536:            }
0537:
0538:            /**
0539:             * if the given classname is stored in the classname override hashtable, 
0540:             * then the override name is returned otherwise the given classname.
0541:             * <b>Note:</b> in contrast to <code>overrideClassname(Object)</code> does
0542:             * this method only look for exact name matches. The other method checks
0543:             * whether the class of the given object is a subclass of any of the stored
0544:             * overrides.  
0545:             * 
0546:             * @param classname  the classname to check for overriding
0547:             * @return           if overridden then the classname stored in the hashtable,
0548:             *                   otherwise the given classname
0549:             * @see              #m_ClassnameOverride
0550:             * @see              #overrideClassname(Object)
0551:             */
0552:            protected String overrideClassname(String classname) {
0553:                Enumeration enm;
0554:                String result;
0555:                Class currentCls;
0556:
0557:                result = classname;
0558:
0559:                // check overrides
0560:                enm = m_ClassnameOverride.keys();
0561:                while (enm.hasMoreElements()) {
0562:                    currentCls = (Class) enm.nextElement();
0563:                    if (currentCls.getName().equals(classname)) {
0564:                        result = (String) m_ClassnameOverride.get(currentCls);
0565:                        break;
0566:                    }
0567:                }
0568:
0569:                return result;
0570:            }
0571:
0572:            /**
0573:             * returns a property descriptor if possible, otherwise <code>null</code>
0574:             * 
0575:             * @param className the name of the class to get the descriptor for
0576:             * @param displayName the name of the property
0577:             * @return the descriptor if available, otherwise <code>null</code>
0578:             */
0579:            protected PropertyDescriptor determineDescriptor(String className,
0580:                    String displayName) {
0581:                PropertyDescriptor result;
0582:
0583:                result = null;
0584:
0585:                try {
0586:                    result = new PropertyDescriptor(displayName, Class
0587:                            .forName(className));
0588:                } catch (Exception e) {
0589:                    result = null;
0590:                }
0591:
0592:                return result;
0593:            }
0594:
0595:            /**
0596:             * adds the given primitive to the DOM structure.
0597:             * @param parent the parent of this object, e.g. the class this object is a member of
0598:             * @param o the primitive to describe in XML
0599:             * @param name the name of the primitive
0600:             * @return the node that was created
0601:             * @throws Exception if the DOM creation fails
0602:             */
0603:            protected Element writeBooleanToXML(Element parent, boolean o,
0604:                    String name) throws Exception {
0605:                Element node;
0606:
0607:                // for debugging only
0608:                if (DEBUG)
0609:                    trace(new Throwable(), name);
0610:
0611:                m_CurrentNode = parent;
0612:
0613:                node = addElement(parent, name, Boolean.TYPE.getName(), true);
0614:                node.appendChild(node.getOwnerDocument().createTextNode(
0615:                        new Boolean(o).toString()));
0616:
0617:                return node;
0618:            }
0619:
0620:            /**
0621:             * adds the given primitive to the DOM structure.
0622:             * @param parent the parent of this object, e.g. the class this object is a member of
0623:             * @param o the primitive to describe in XML
0624:             * @param name the name of the primitive
0625:             * @return the node that was created
0626:             * @throws Exception if the DOM creation fails
0627:             */
0628:            protected Element writeByteToXML(Element parent, byte o, String name)
0629:                    throws Exception {
0630:                Element node;
0631:
0632:                // for debugging only
0633:                if (DEBUG)
0634:                    trace(new Throwable(), name);
0635:
0636:                m_CurrentNode = parent;
0637:
0638:                node = addElement(parent, name, Byte.TYPE.getName(), true);
0639:                node.appendChild(node.getOwnerDocument().createTextNode(
0640:                        new Byte(o).toString()));
0641:
0642:                return node;
0643:            }
0644:
0645:            /**
0646:             * adds the given primitive to the DOM structure.
0647:             * @param parent the parent of this object, e.g. the class this object is a member of
0648:             * @param o the primitive to describe in XML
0649:             * @param name the name of the primitive
0650:             * @return the node that was created
0651:             * @throws Exception if the DOM creation fails
0652:             */
0653:            protected Element writeCharToXML(Element parent, char o, String name)
0654:                    throws Exception {
0655:                Element node;
0656:
0657:                // for debugging only
0658:                if (DEBUG)
0659:                    trace(new Throwable(), name);
0660:
0661:                m_CurrentNode = parent;
0662:
0663:                node = addElement(parent, name, Character.TYPE.getName(), true);
0664:                node.appendChild(node.getOwnerDocument().createTextNode(
0665:                        new Character(o).toString()));
0666:
0667:                return node;
0668:            }
0669:
0670:            /**
0671:             * adds the given primitive to the DOM structure.
0672:             * @param parent the parent of this object, e.g. the class this object is a member of
0673:             * @param o the primitive to describe in XML
0674:             * @param name the name of the primitive
0675:             * @return the node that was created
0676:             * @throws Exception if the DOM creation fails
0677:             */
0678:            protected Element writeDoubleToXML(Element parent, double o,
0679:                    String name) throws Exception {
0680:                Element node;
0681:
0682:                // for debugging only
0683:                if (DEBUG)
0684:                    trace(new Throwable(), name);
0685:
0686:                m_CurrentNode = parent;
0687:
0688:                node = addElement(parent, name, Double.TYPE.getName(), true);
0689:                node.appendChild(node.getOwnerDocument().createTextNode(
0690:                        new Double(o).toString()));
0691:
0692:                return node;
0693:            }
0694:
0695:            /**
0696:             * adds the given primitive to the DOM structure.
0697:             * @param parent the parent of this object, e.g. the class this object is a member of
0698:             * @param o the primitive to describe in XML
0699:             * @param name the name of the primitive
0700:             * @return the node that was created
0701:             * @throws Exception if the DOM creation fails
0702:             */
0703:            protected Element writeFloatToXML(Element parent, float o,
0704:                    String name) throws Exception {
0705:                Element node;
0706:
0707:                // for debugging only
0708:                if (DEBUG)
0709:                    trace(new Throwable(), name);
0710:
0711:                m_CurrentNode = parent;
0712:
0713:                node = addElement(parent, name, Float.TYPE.getName(), true);
0714:                node.appendChild(node.getOwnerDocument().createTextNode(
0715:                        new Float(o).toString()));
0716:
0717:                return node;
0718:            }
0719:
0720:            /**
0721:             * adds the given primitive to the DOM structure.
0722:             * @param parent the parent of this object, e.g. the class this object is a member of
0723:             * @param o the primitive to describe in XML
0724:             * @param name the name of the primitive
0725:             * @return the node that was created
0726:             * @throws Exception if the DOM creation fails
0727:             */
0728:            protected Element writeIntToXML(Element parent, int o, String name)
0729:                    throws Exception {
0730:                Element node;
0731:
0732:                // for debugging only
0733:                if (DEBUG)
0734:                    trace(new Throwable(), name);
0735:
0736:                m_CurrentNode = parent;
0737:
0738:                node = addElement(parent, name, Integer.TYPE.getName(), true);
0739:                node.appendChild(node.getOwnerDocument().createTextNode(
0740:                        new Integer(o).toString()));
0741:
0742:                return node;
0743:            }
0744:
0745:            /**
0746:             * adds the given primitive to the DOM structure.
0747:             * @param parent the parent of this object, e.g. the class this object is a member of
0748:             * @param o the primitive to describe in XML
0749:             * @param name the name of the primitive
0750:             * @return the node that was created
0751:             * @throws Exception if the DOM creation fails
0752:             */
0753:            protected Element writeLongToXML(Element parent, long o, String name)
0754:                    throws Exception {
0755:                Element node;
0756:
0757:                // for debugging only
0758:                if (DEBUG)
0759:                    trace(new Throwable(), name);
0760:
0761:                m_CurrentNode = parent;
0762:
0763:                node = addElement(parent, name, Long.TYPE.getName(), true);
0764:                node.appendChild(node.getOwnerDocument().createTextNode(
0765:                        new Long(o).toString()));
0766:
0767:                return node;
0768:            }
0769:
0770:            /**
0771:             * adds the given primitive to the DOM structure.
0772:             * @param parent the parent of this object, e.g. the class this object is a member of
0773:             * @param o the primitive to describe in XML
0774:             * @param name the name of the primitive
0775:             * @return the node that was created
0776:             * @throws Exception if the DOM creation fails
0777:             */
0778:            protected Element writeShortToXML(Element parent, short o,
0779:                    String name) throws Exception {
0780:                Element node;
0781:
0782:                // for debugging only
0783:                if (DEBUG)
0784:                    trace(new Throwable(), name);
0785:
0786:                m_CurrentNode = parent;
0787:
0788:                node = addElement(parent, name, Short.TYPE.getName(), true);
0789:                node.appendChild(node.getOwnerDocument().createTextNode(
0790:                        new Short(o).toString()));
0791:
0792:                return node;
0793:            }
0794:
0795:            /**
0796:             * checks whether the innermost class is a primitive class (handles 
0797:             * multi-dimensional arrays)
0798:             * @param c        the array class to inspect
0799:             * @return         whether the array consists of primitive elements
0800:             */
0801:            protected boolean isPrimitiveArray(Class c) {
0802:                if (c.getComponentType().isArray())
0803:                    return isPrimitiveArray(c.getComponentType());
0804:                else
0805:                    return c.getComponentType().isPrimitive();
0806:            }
0807:
0808:            /**
0809:             * adds the given Object to a DOM structure. 
0810:             * (only public due to reflection).<br>
0811:             * <b>Note:</b> <code>overrideClassname(Object)</code> is not invoked in case of
0812:             * arrays, since the array class could be a superclass, whereas the elements of
0813:             * the array can be specialized subclasses. In case of an array the method 
0814:             * <code>overrideClassname(String)</code> is invoked, which searches for an 
0815:             * exact match of the classname in the override hashtable.
0816:             * 
0817:             * @param parent the parent of this object, e.g. the class this object is a member of
0818:             * @param o the Object to describe in XML
0819:             * @param name the name of the object
0820:             * @return the node that was created
0821:             * @throws Exception if the DOM creation fails
0822:             * @see #overrideClassname(Object)
0823:             * @see #overrideClassname(String)
0824:             * @see #m_ClassnameOverride
0825:             */
0826:            public Element writeToXML(Element parent, Object o, String name)
0827:                    throws Exception {
0828:                String classname;
0829:                Element node;
0830:                Hashtable memberlist;
0831:                Enumeration enm;
0832:                Object member;
0833:                String memberName;
0834:                Method method;
0835:                PropertyDescriptor desc;
0836:                boolean primitive;
0837:                int array;
0838:                int i;
0839:                Object obj;
0840:                String tmpStr;
0841:
0842:                node = null;
0843:
0844:                // for debugging only
0845:                if (DEBUG)
0846:                    trace(new Throwable(), name);
0847:
0848:                // special handling of null-objects
0849:                if (o == null) {
0850:                    node = addElement(parent, name, "" + null, false, 0, true);
0851:                    return node;
0852:                }
0853:
0854:                // used for overriding the classname
0855:                obj = null;
0856:
0857:                // get information about object
0858:                array = 0;
0859:                if (o.getClass().isArray())
0860:                    array = Utils.getArrayDimensions(o);
0861:                if (array > 0) {
0862:                    classname = Utils.getArrayClass(o.getClass()).getName();
0863:                    primitive = isPrimitiveArray(o.getClass());
0864:                } else {
0865:                    // try to get property descriptor to determine real class
0866:                    // (for primitives the getClass() method returns the corresponding Object-Class!)
0867:                    desc = null;
0868:                    if (parent != null)
0869:                        desc = determineDescriptor(parent
0870:                                .getAttribute(ATT_CLASS), name);
0871:
0872:                    if (desc != null)
0873:                        primitive = desc.getPropertyType().isPrimitive();
0874:                    else
0875:                        primitive = o.getClass().isPrimitive();
0876:
0877:                    // for primitives: retrieve primitive type, otherwise the object's real 
0878:                    // class. For non-primitives we can't use the descriptor, since that
0879:                    // might only return an interface as class!
0880:                    if (primitive) {
0881:                        classname = desc.getPropertyType().getName();
0882:                    } else {
0883:                        obj = o;
0884:                        classname = o.getClass().getName();
0885:                    }
0886:                }
0887:
0888:                // fix class/primitive if parent is array of primitives, thanks to 
0889:                // reflection the elements of the array are objects and not primitives!
0890:                if ((parent != null)
0891:                        && (!parent.getAttribute(ATT_ARRAY).equals(""))
0892:                        && (!parent.getAttribute(ATT_ARRAY).equals(VAL_NO))
0893:                        && (stringToBoolean(parent.getAttribute(ATT_PRIMITIVE)))) {
0894:                    primitive = true;
0895:                    classname = parent.getAttribute(ATT_CLASS);
0896:                    obj = null;
0897:                }
0898:
0899:                // perhaps we need to override the classname
0900:                if (obj != null)
0901:                    classname = overrideClassname(obj); // for non-arrays
0902:                else
0903:                    classname = overrideClassname(classname); // for arrays
0904:
0905:                // create node for current object
0906:                node = addElement(parent, name, classname, primitive, array);
0907:
0908:                // array? -> save as child with 'name="<index>"'
0909:                if (array > 0) {
0910:                    for (i = 0; i < Array.getLength(o); i++) {
0911:                        invokeWriteToXML(node, Array.get(o, i), Integer
0912:                                .toString(i));
0913:                    }
0914:                }
0915:                // non-array
0916:                else {
0917:                    // primitive? -> only toString()
0918:                    if (primitive) {
0919:                        node.appendChild(node.getOwnerDocument()
0920:                                .createTextNode(o.toString()));
0921:                    }
0922:                    // object
0923:                    else {
0924:                        // process recursively members of this object 
0925:                        memberlist = getDescriptors(o);
0926:                        // if no get/set methods -> we assume it has String-Constructor
0927:                        if (memberlist.size() == 0) {
0928:                            if (!o.toString().equals("")) {
0929:                                tmpStr = o.toString();
0930:                                // these five entities are recognized by every XML processor
0931:                                // see http://www.xml.com/pub/a/2001/03/14/trxml10.html
0932:                                tmpStr = tmpStr.replaceAll("&", "&amp;")
0933:                                        .replaceAll("\"", "&quot;").replaceAll(
0934:                                                "'", "&apos;").replaceAll("<",
0935:                                                "&lt;").replaceAll(">", "&gt;");
0936:                                // in addition, replace some other entities as well
0937:                                tmpStr = tmpStr.replaceAll("\n", "&#10;")
0938:                                        .replaceAll("\r", "&#13;").replaceAll(
0939:                                                "\t", "&#9;");
0940:                                node.appendChild(node.getOwnerDocument()
0941:                                        .createTextNode(tmpStr));
0942:                            }
0943:                        } else {
0944:                            enm = memberlist.keys();
0945:                            while (enm.hasMoreElements()) {
0946:                                memberName = enm.nextElement().toString();
0947:
0948:                                // in ignore list?
0949:                                if ((m_Properties.isIgnored(memberName))
0950:                                        || (m_Properties
0951:                                                .isIgnored(getPath(node) + "."
0952:                                                        + memberName))
0953:                                        || (m_Properties.isIgnored(o,
0954:                                                getPath(node) + "."
0955:                                                        + memberName)))
0956:                                    continue;
0957:
0958:                                // is it allowed?
0959:                                if (!m_Properties.isAllowed(o, memberName))
0960:                                    continue;
0961:
0962:                                desc = (PropertyDescriptor) memberlist
0963:                                        .get(memberName);
0964:                                method = desc.getReadMethod();
0965:                                member = method.invoke(o, (Object[]) null);
0966:                                invokeWriteToXML(node, member, memberName);
0967:                            }
0968:                        }
0969:                    }
0970:                }
0971:
0972:                return node;
0973:            }
0974:
0975:            /**
0976:             * either invokes a custom method to write a specific property/class or the standard
0977:             * method <code>writeToXML(Element,Object,String)</code>
0978:             * 
0979:             * @param parent the parent XML node
0980:             * @param o the object's content will be added as children to the given parent node
0981:             * @param name the name of the object
0982:             * @return the node that was created
0983:             * @throws Exception if invocation or turning into XML fails
0984:             */
0985:            protected Element invokeWriteToXML(Element parent, Object o,
0986:                    String name) throws Exception {
0987:                Method method;
0988:                Class[] methodClasses;
0989:                Object[] methodArgs;
0990:                boolean array;
0991:                Element node;
0992:                boolean useDefault;
0993:
0994:                node = null;
0995:                method = null;
0996:                useDefault = false;
0997:
0998:                m_CurrentNode = parent;
0999:
1000:                // default, if null
1001:                if (o == null)
1002:                    useDefault = true;
1003:
1004:                try {
1005:                    if (!useDefault) {
1006:                        array = o.getClass().isArray();
1007:
1008:                        // display name?
1009:                        if (m_CustomMethods.write().contains(name))
1010:                            method = (Method) m_CustomMethods.write().get(
1011:                                    o.getClass());
1012:                        else
1013:                        // class?
1014:                        if ((!array)
1015:                                && (m_CustomMethods.write().contains(o
1016:                                        .getClass())))
1017:                            method = (Method) m_CustomMethods.write().get(
1018:                                    o.getClass());
1019:                        else
1020:                            method = null;
1021:
1022:                        useDefault = (method == null);
1023:                    }
1024:
1025:                    // custom
1026:                    if (!useDefault) {
1027:                        methodClasses = new Class[3];
1028:                        methodClasses[0] = Element.class;
1029:                        methodClasses[1] = Object.class;
1030:                        methodClasses[2] = String.class;
1031:                        methodArgs = new Object[3];
1032:                        methodArgs[0] = parent;
1033:                        methodArgs[1] = o;
1034:                        methodArgs[2] = name;
1035:                        node = (Element) method.invoke(this , methodArgs);
1036:                    }
1037:                    // standard
1038:                    else {
1039:                        node = writeToXML(parent, o, name);
1040:                    }
1041:                } catch (Exception e) {
1042:                    if (DEBUG)
1043:                        e.printStackTrace();
1044:
1045:                    if (m_CurrentNode != null) {
1046:                        System.out.println("Happened near: "
1047:                                + getPath(m_CurrentNode));
1048:                        // print it only once!
1049:                        m_CurrentNode = null;
1050:                    }
1051:                    System.out.println("PROBLEM (write): " + name);
1052:
1053:                    throw (Exception) e.fillInStackTrace();
1054:                }
1055:
1056:                return node;
1057:            }
1058:
1059:            /**
1060:             * enables derived classes to due some pre-processing on the objects, that's
1061:             * about to be serialized. Right now it only returns the object.
1062:             * 
1063:             * @param o the object that is serialized into XML
1064:             * @return the possibly altered object
1065:             * @throws Exception if post-processing fails
1066:             */
1067:            protected Object writePreProcess(Object o) throws Exception {
1068:                return o;
1069:            }
1070:
1071:            /**
1072:             * enables derived classes to add other properties to the DOM tree, e.g.
1073:             * ones that do not apply to the get/set convention of beans. only implemented
1074:             * with empty method body.
1075:             * 
1076:             * @param o the object that is serialized into XML
1077:             * @throws Exception if post-processing fails
1078:             */
1079:            protected void writePostProcess(Object o) throws Exception {
1080:            }
1081:
1082:            /**
1083:             * extracts all accesible properties from the given object
1084:             * 
1085:             * @param o the object to turn into an XML representation
1086:             * @return the generated DOM document 
1087:             * @throws Exception if XML generation fails 
1088:             */
1089:            public XMLDocument toXML(Object o) throws Exception {
1090:                clear();
1091:                invokeWriteToXML(null, writePreProcess(o), VAL_ROOT);
1092:                writePostProcess(o);
1093:                return m_Document;
1094:            }
1095:
1096:            /**
1097:             * returns a descriptor for a given objet by providing the name
1098:             * 
1099:             * @param o the object the get the descriptor for
1100:             * @param name the display name of the descriptor
1101:             * @return the Descriptor, if found, otherwise <code>null</code>
1102:             * @throws Exception if introsepction fails 
1103:             */
1104:            protected PropertyDescriptor getDescriptorByName(Object o,
1105:                    String name) throws Exception {
1106:                PropertyDescriptor result;
1107:                PropertyDescriptor[] desc;
1108:                int i;
1109:
1110:                result = null;
1111:
1112:                desc = Introspector.getBeanInfo(o.getClass())
1113:                        .getPropertyDescriptors();
1114:                for (i = 0; i < desc.length; i++) {
1115:                    if (desc[i].getDisplayName().equals(name)) {
1116:                        result = desc[i];
1117:                        break;
1118:                    }
1119:                }
1120:
1121:                return result;
1122:            }
1123:
1124:            /**
1125:             * returns the associated class for the given name
1126:             * 
1127:             * @param name the name of the class to return a Class object for
1128:             * @return the class if  it could be retrieved
1129:             * @throws Exception if it class retrieval fails
1130:             */
1131:            protected Class determineClass(String name) throws Exception {
1132:                Class result;
1133:
1134:                if (name.equals(Boolean.TYPE.getName()))
1135:                    result = Boolean.TYPE;
1136:                else if (name.equals(Byte.TYPE.getName()))
1137:                    result = Byte.TYPE;
1138:                else if (name.equals(Character.TYPE.getName()))
1139:                    result = Character.TYPE;
1140:                else if (name.equals(Double.TYPE.getName()))
1141:                    result = Double.TYPE;
1142:                else if (name.equals(Float.TYPE.getName()))
1143:                    result = Float.TYPE;
1144:                else if (name.equals(Integer.TYPE.getName()))
1145:                    result = Integer.TYPE;
1146:                else if (name.equals(Long.TYPE.getName()))
1147:                    result = Long.TYPE;
1148:                else if (name.equals(Short.TYPE.getName()))
1149:                    result = Short.TYPE;
1150:                else
1151:                    result = Class.forName(name);
1152:
1153:                return result;
1154:            }
1155:
1156:            /**
1157:             * returns an Object representing the primitive described by the given node.
1158:             * Here we use a trick to return an object even though its a primitive: by 
1159:             * creating a primitive array with reflection of length 1, setting the 
1160:             * primtive value as real object and then returning the "object" at 
1161:             * position 1 of the array.
1162:             * 
1163:             * @param node the node to return the value as "primitive" object
1164:             * @return the primitive as "pseudo" object
1165:             * @throws Exception if the instantiation of the array fails or any of the
1166:             *         String conversions fails
1167:             */
1168:            protected Object getPrimitive(Element node) throws Exception {
1169:                Object result;
1170:                Object tmpResult;
1171:                Class cls;
1172:
1173:                cls = determineClass(node.getAttribute(ATT_CLASS));
1174:                tmpResult = Array.newInstance(cls, 1);
1175:
1176:                if (cls == Boolean.TYPE)
1177:                    Array.set(tmpResult, 0, new Boolean(XMLDocument
1178:                            .getContent(node)));
1179:                else if (cls == Byte.TYPE)
1180:                    Array.set(tmpResult, 0, new Byte(XMLDocument
1181:                            .getContent(node)));
1182:                else if (cls == Character.TYPE)
1183:                    Array.set(tmpResult, 0, new Character(XMLDocument
1184:                            .getContent(node).charAt(0)));
1185:                else if (cls == Double.TYPE)
1186:                    Array.set(tmpResult, 0, new Double(XMLDocument
1187:                            .getContent(node)));
1188:                else if (cls == Float.TYPE)
1189:                    Array.set(tmpResult, 0, new Float(XMLDocument
1190:                            .getContent(node)));
1191:                else if (cls == Integer.TYPE)
1192:                    Array.set(tmpResult, 0, new Integer(XMLDocument
1193:                            .getContent(node)));
1194:                else if (cls == Long.TYPE)
1195:                    Array.set(tmpResult, 0, new Long(XMLDocument
1196:                            .getContent(node)));
1197:                else if (cls == Short.TYPE)
1198:                    Array.set(tmpResult, 0, new Short(XMLDocument
1199:                            .getContent(node)));
1200:                else
1201:                    throw new Exception("Cannot get primitive for class '"
1202:                            + cls.getName() + "'!");
1203:
1204:                result = Array.get(tmpResult, 0);
1205:
1206:                return result;
1207:            }
1208:
1209:            /**
1210:             * builds the primitive from the given DOM node. 
1211:             * 
1212:             * @param node the associated XML node
1213:             * @return the primitive created from the XML description
1214:             * @throws Exception if instantiation fails 
1215:             */
1216:            public boolean readBooleanFromXML(Element node) throws Exception {
1217:                // for debugging only
1218:                if (DEBUG)
1219:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1220:
1221:                m_CurrentNode = node;
1222:
1223:                return ((Boolean) getPrimitive(node)).booleanValue();
1224:            }
1225:
1226:            /**
1227:             * builds the primitive from the given DOM node. 
1228:             * 
1229:             * @param node the associated XML node
1230:             * @return the primitive created from the XML description
1231:             * @throws Exception if instantiation fails 
1232:             */
1233:            public byte readByteFromXML(Element node) throws Exception {
1234:                // for debugging only
1235:                if (DEBUG)
1236:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1237:
1238:                m_CurrentNode = node;
1239:
1240:                return ((Byte) getPrimitive(node)).byteValue();
1241:            }
1242:
1243:            /**
1244:             * builds the primitive from the given DOM node. 
1245:             * 
1246:             * @param node the associated XML node
1247:             * @return the primitive created from the XML description
1248:             * @throws Exception if instantiation fails 
1249:             */
1250:            public char readCharFromXML(Element node) throws Exception {
1251:                // for debugging only
1252:                if (DEBUG)
1253:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1254:
1255:                m_CurrentNode = node;
1256:
1257:                return ((Character) getPrimitive(node)).charValue();
1258:            }
1259:
1260:            /**
1261:             * builds the primitive from the given DOM node. 
1262:             * 
1263:             * @param node the associated XML node
1264:             * @return the primitive created from the XML description
1265:             * @throws Exception if instantiation fails 
1266:             */
1267:            public double readDoubleFromXML(Element node) throws Exception {
1268:                // for debugging only
1269:                if (DEBUG)
1270:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1271:
1272:                m_CurrentNode = node;
1273:
1274:                return ((Double) getPrimitive(node)).doubleValue();
1275:            }
1276:
1277:            /**
1278:             * builds the primitive from the given DOM node. 
1279:             * 
1280:             * @param node the associated XML node
1281:             * @return the primitive created from the XML description
1282:             * @throws Exception if instantiation fails 
1283:             */
1284:            public float readFloatFromXML(Element node) throws Exception {
1285:                // for debugging only
1286:                if (DEBUG)
1287:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1288:
1289:                m_CurrentNode = node;
1290:
1291:                return ((Float) getPrimitive(node)).floatValue();
1292:            }
1293:
1294:            /**
1295:             * builds the primitive from the given DOM node. 
1296:             * 
1297:             * @param node the associated XML node
1298:             * @return the primitive created from the XML description
1299:             * @throws Exception if instantiation fails 
1300:             */
1301:            public int readIntFromXML(Element node) throws Exception {
1302:                // for debugging only
1303:                if (DEBUG)
1304:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1305:
1306:                m_CurrentNode = node;
1307:
1308:                return ((Integer) getPrimitive(node)).intValue();
1309:            }
1310:
1311:            /**
1312:             * builds the primitive from the given DOM node. 
1313:             * 
1314:             * @param node the associated XML node
1315:             * @return the primitive created from the XML description
1316:             * @throws Exception if instantiation fails 
1317:             */
1318:            public long readLongFromXML(Element node) throws Exception {
1319:                // for debugging only
1320:                if (DEBUG)
1321:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1322:
1323:                m_CurrentNode = node;
1324:
1325:                return ((Long) getPrimitive(node)).longValue();
1326:            }
1327:
1328:            /**
1329:             * builds the primitive from the given DOM node. 
1330:             * 
1331:             * @param node the associated XML node
1332:             * @return the primitive created from the XML description
1333:             * @throws Exception if instantiation fails 
1334:             */
1335:            public short readShortFromXML(Element node) throws Exception {
1336:                // for debugging only
1337:                if (DEBUG)
1338:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1339:
1340:                m_CurrentNode = node;
1341:
1342:                return ((Short) getPrimitive(node)).shortValue();
1343:            }
1344:
1345:            /**
1346:             * adds the specific node to the object via a set method
1347:             * 
1348:             * @param o            the object to set a property
1349:             * @param name         the name of the object for which to set a property
1350:             *                     (only for information reasons)
1351:             * @param child        the value of the property to add
1352:             * @return             the provided object, but augmented by the child
1353:             * @throws Exception   if something goes wrong
1354:             */
1355:            public Object readFromXML(Object o, String name, Element child)
1356:                    throws Exception {
1357:                Object result;
1358:                Hashtable descriptors;
1359:                PropertyDescriptor descriptor;
1360:                String methodName;
1361:                Method method;
1362:                Object[] methodArgs;
1363:                Object tmpResult;
1364:                Class paramClass;
1365:
1366:                result = o;
1367:                descriptors = getDescriptors(result);
1368:                methodName = child.getAttribute(ATT_NAME);
1369:
1370:                // in ignore list?
1371:                if (m_Properties.isIgnored(getPath(child)))
1372:                    return result;
1373:
1374:                // in ignore list of class?
1375:                if (m_Properties.isIgnored(result, getPath(child)))
1376:                    return result;
1377:
1378:                // is it allowed?
1379:                if (!m_Properties.isAllowed(result, methodName))
1380:                    return result;
1381:
1382:                descriptor = (PropertyDescriptor) descriptors.get(methodName);
1383:
1384:                // unknown property?
1385:                if (descriptor == null) {
1386:                    if (!m_CustomMethods.read().contains(methodName))
1387:                        System.out.println("WARNING: unknown property '" + name
1388:                                + "." + methodName + "'!");
1389:                    return result;
1390:                }
1391:
1392:                method = descriptor.getWriteMethod();
1393:                methodArgs = new Object[1];
1394:                tmpResult = invokeReadFromXML(child);
1395:                paramClass = method.getParameterTypes()[0];
1396:
1397:                // array?
1398:                if (paramClass.isArray()) {
1399:                    // no data?
1400:                    if (Array.getLength(tmpResult) == 0)
1401:                        return result;
1402:                    methodArgs[0] = (Object[]) tmpResult;
1403:                }
1404:                // non-array
1405:                else {
1406:                    methodArgs[0] = tmpResult;
1407:                }
1408:
1409:                method.invoke(result, methodArgs);
1410:
1411:                return result;
1412:            }
1413:
1414:            /**
1415:             * returns an array with the dimensions of the array stored in XML
1416:             * @param node the node to determine the dimensions for
1417:             * @return the dimensions of the array
1418:             */
1419:            protected int[] getArrayDimensions(Element node) {
1420:                Vector children;
1421:                Vector tmpVector;
1422:                int[] tmp;
1423:                int[] result;
1424:                int i;
1425:
1426:                // have we reached the innermost dimension?
1427:                if (stringToBoolean(node.getAttribute(ATT_ARRAY)))
1428:                    children = XMLDocument.getChildTags(node);
1429:                else
1430:                    children = null;
1431:
1432:                if (children != null) {
1433:                    tmpVector = new Vector();
1434:
1435:                    if (children.size() > 0) {
1436:                        // are children also arrays?
1437:                        tmp = getArrayDimensions((Element) children.get(0));
1438:
1439:                        // further dimensions
1440:                        if (tmp != null) {
1441:                            for (i = tmp.length - 1; i >= 0; i--)
1442:                                tmpVector.add(new Integer(tmp[i]));
1443:                        }
1444:
1445:                        // add current dimension
1446:                        tmpVector.add(0, new Integer(children.size()));
1447:                    } else {
1448:                        tmpVector.add(new Integer(0));
1449:                    }
1450:
1451:                    // generate result
1452:                    result = new int[tmpVector.size()];
1453:                    for (i = 0; i < result.length; i++)
1454:                        result[i] = ((Integer) tmpVector.get(tmpVector.size()
1455:                                - i - 1)).intValue();
1456:                } else {
1457:                    result = null;
1458:                }
1459:
1460:                return result;
1461:            }
1462:
1463:            /**
1464:             * builds the object from the given DOM node. 
1465:             * (only public due to reflection) 
1466:             * 
1467:             * @param node the associated XML node
1468:             * @return the instance created from the XML description
1469:             * @throws Exception if instantiation fails 
1470:             */
1471:            public Object readFromXML(Element node) throws Exception {
1472:                String classname;
1473:                String name;
1474:                boolean primitive;
1475:                boolean array;
1476:                boolean isnull;
1477:                Class cls;
1478:                Vector children;
1479:                Object result;
1480:                int i;
1481:                Constructor constructor;
1482:                Class[] methodClasses;
1483:                Object[] methodArgs;
1484:                Element child;
1485:
1486:                // for debugging only
1487:                if (DEBUG)
1488:                    trace(new Throwable(), node.getAttribute(ATT_NAME));
1489:
1490:                m_CurrentNode = node;
1491:
1492:                result = null;
1493:
1494:                name = node.getAttribute(ATT_NAME);
1495:                classname = node.getAttribute(ATT_CLASS);
1496:                primitive = stringToBoolean(node.getAttribute(ATT_PRIMITIVE));
1497:                array = stringToBoolean(node.getAttribute(ATT_ARRAY));
1498:                isnull = stringToBoolean(node.getAttribute(ATT_NULL));
1499:
1500:                // special handling of null
1501:                if (isnull)
1502:                    return result;
1503:
1504:                children = XMLDocument.getChildTags(node);
1505:                cls = determineClass(classname);
1506:
1507:                // array
1508:                if (array) {
1509:                    result = Array.newInstance(cls, getArrayDimensions(node));
1510:                    for (i = 0; i < children.size(); i++) {
1511:                        child = (Element) children.get(i);
1512:                        Array.set(result, Integer.parseInt(child
1513:                                .getAttribute(ATT_NAME)),
1514:                                invokeReadFromXML(child));
1515:                    }
1516:                }
1517:                // non-array
1518:                else {
1519:                    // primitive/String-constructor
1520:                    if (children.size() == 0) {
1521:                        // primitive
1522:                        if (primitive) {
1523:                            result = getPrimitive(node);
1524:                        }
1525:                        // assumed String-constructor
1526:                        else {
1527:                            methodClasses = new Class[1];
1528:                            methodClasses[0] = String.class;
1529:                            methodArgs = new Object[1];
1530:                            methodArgs[0] = XMLDocument.getContent(node);
1531:                            try {
1532:                                constructor = cls.getConstructor(methodClasses);
1533:                                result = constructor.newInstance(methodArgs);
1534:                            } catch (Exception e) {
1535:                                // if it's not a class with String constructor, let's try standard constructor
1536:                                try {
1537:                                    result = cls.newInstance();
1538:                                } catch (Exception e2) {
1539:                                    // sorry, can't instantiate!
1540:                                    result = null;
1541:                                    System.out
1542:                                            .println("ERROR: Can't instantiate '"
1543:                                                    + classname + "'!");
1544:                                }
1545:                            }
1546:                        }
1547:                    }
1548:                    // normal get/set methods
1549:                    else {
1550:                        result = cls.newInstance();
1551:                        for (i = 0; i < children.size(); i++)
1552:                            result = readFromXML(result, name,
1553:                                    (Element) children.get(i));
1554:                    }
1555:                }
1556:
1557:                return result;
1558:            }
1559:
1560:            /**
1561:             * either invokes a custom method to read a specific property/class or the standard
1562:             * method <code>readFromXML(Element)</code>
1563:             * 
1564:             * @param node the associated XML node
1565:             * @return the instance created from the XML description
1566:             * @throws Exception if instantiation fails
1567:             */
1568:            protected Object invokeReadFromXML(Element node) throws Exception {
1569:                Method method;
1570:                Class[] methodClasses;
1571:                Object[] methodArgs;
1572:                boolean array;
1573:                boolean useDefault;
1574:
1575:                useDefault = false;
1576:                method = null;
1577:                m_CurrentNode = node;
1578:
1579:                try {
1580:                    // special handling of null values
1581:                    if (stringToBoolean(node.getAttribute(ATT_NULL)))
1582:                        useDefault = true;
1583:
1584:                    if (!useDefault) {
1585:                        array = stringToBoolean(node.getAttribute(ATT_ARRAY));
1586:
1587:                        // display name?
1588:                        if (m_CustomMethods.read().contains(
1589:                                node.getAttribute(ATT_NAME)))
1590:                            method = (Method) m_CustomMethods.read().get(
1591:                                    node.getAttribute(ATT_NAME));
1592:                        else
1593:                        // class name?
1594:                        if ((!array)
1595:                                && (m_CustomMethods.read()
1596:                                        .contains(determineClass(node
1597:                                                .getAttribute(ATT_CLASS)))))
1598:                            method = (Method) m_CustomMethods.read()
1599:                                    .get(
1600:                                            determineClass(node
1601:                                                    .getAttribute(ATT_CLASS)));
1602:                        else
1603:                            method = null;
1604:
1605:                        useDefault = (method == null);
1606:                    }
1607:
1608:                    // custom method
1609:                    if (!useDefault) {
1610:                        methodClasses = new Class[1];
1611:                        methodClasses[0] = Element.class;
1612:                        methodArgs = new Object[1];
1613:                        methodArgs[0] = node;
1614:                        return method.invoke(this , methodArgs);
1615:                    }
1616:                    // standard
1617:                    else {
1618:                        return readFromXML(node);
1619:                    }
1620:                } catch (Exception e) {
1621:                    if (DEBUG)
1622:                        e.printStackTrace();
1623:
1624:                    if (m_CurrentNode != null) {
1625:                        System.out.println("Happened near: "
1626:                                + getPath(m_CurrentNode));
1627:                        // print it only once!
1628:                        m_CurrentNode = null;
1629:                    }
1630:                    System.out.println("PROBLEM (read): "
1631:                            + node.getAttribute("name"));
1632:
1633:                    throw (Exception) e.fillInStackTrace();
1634:                }
1635:            }
1636:
1637:            /**
1638:             * additional pre-processing can happen in derived classes before the 
1639:             * actual reading from XML (working on the raw XML). right now it does 
1640:             * nothing with the document.
1641:             * 
1642:             * @param document 	the document to pre-process
1643:             * @return the processed object
1644:             * @throws Exception if post-processing fails
1645:             */
1646:            protected Document readPreProcess(Document document)
1647:                    throws Exception {
1648:                return document;
1649:            }
1650:
1651:            /**
1652:             * additional post-processing can happen in derived classes after reading 
1653:             * from XML. right now it only returns the object as it is.
1654:             * 
1655:             * @param o the object to perform some additional processing on
1656:             * @return the processed object
1657:             * @throws Exception if post-processing fails
1658:             */
1659:            protected Object readPostProcess(Object o) throws Exception {
1660:                return o;
1661:            }
1662:
1663:            /**
1664:             * returns the given DOM document as an instance of the specified class
1665:             * 
1666:             * @param document the parsed DOM document representing the object
1667:             * @return the XML as object 
1668:             * @throws Exception if object instantiation fails
1669:             */
1670:            public Object fromXML(Document document) throws Exception {
1671:                if (!document.getDocumentElement().getNodeName().equals(
1672:                        ROOT_NODE))
1673:                    throw new Exception("Expected '" + ROOT_NODE
1674:                            + "' as root element, but found '"
1675:                            + document.getDocumentElement().getNodeName()
1676:                            + "'!");
1677:                m_Document.setDocument(readPreProcess(document));
1678:                checkVersion();
1679:                return readPostProcess(invokeReadFromXML(m_Document
1680:                        .getDocument().getDocumentElement()));
1681:            }
1682:
1683:            /**
1684:             * parses the given XML string (can be XML or a filename) and returns an
1685:             * Object generated from the representation
1686:             * 
1687:             * @param xml the xml to parse (if "<?xml" is not found then it is considered a file)
1688:             * @return the generated instance
1689:             * @throws Exception if something goes wrong with the parsing
1690:             */
1691:            public Object read(String xml) throws Exception {
1692:                return fromXML(m_Document.read(xml));
1693:            }
1694:
1695:            /**
1696:             * parses the given file and returns a DOM document
1697:             * 
1698:             * @param file the XML file to parse
1699:             * @return the parsed DOM document
1700:             * @throws Exception if something goes wrong with the parsing
1701:             */
1702:            public Object read(File file) throws Exception {
1703:                return fromXML(m_Document.read(file));
1704:            }
1705:
1706:            /**
1707:             * parses the given stream and returns a DOM document
1708:             * 
1709:             * @param stream the XML stream to parse
1710:             * @return the parsed DOM document
1711:             * @throws Exception if something goes wrong with the parsing
1712:             */
1713:            public Object read(InputStream stream) throws Exception {
1714:                return fromXML(m_Document.read(stream));
1715:            }
1716:
1717:            /**
1718:             * parses the given reader and returns a DOM document
1719:             * 
1720:             * @param reader the XML reader to parse
1721:             * @return the parsed DOM document
1722:             * @throws Exception if something goes wrong with the parsing
1723:             */
1724:            public Object read(Reader reader) throws Exception {
1725:                return fromXML(m_Document.read(reader));
1726:            }
1727:
1728:            /**
1729:             * writes the given object into the file
1730:             * 
1731:             * @param file the filename to write to
1732:             * @param o the object to serialize as XML
1733:             * @throws Exception if something goes wrong with the parsing
1734:             */
1735:            public void write(String file, Object o) throws Exception {
1736:                toXML(o).write(file);
1737:            }
1738:
1739:            /**
1740:             * writes the given object into the file
1741:             * 
1742:             * @param file the filename to write to
1743:             * @param o the object to serialize as XML
1744:             * @throws Exception if something goes wrong with the parsing
1745:             */
1746:            public void write(File file, Object o) throws Exception {
1747:                toXML(o).write(file);
1748:            }
1749:
1750:            /**
1751:             * writes the given object into the stream
1752:             * 
1753:             * @param stream the filename to write to
1754:             * @param o the object to serialize as XML
1755:             * @throws Exception if something goes wrong with the parsing
1756:             */
1757:            public void write(OutputStream stream, Object o) throws Exception {
1758:                toXML(o).write(stream);
1759:            }
1760:
1761:            /**
1762:             * writes the given object into the writer
1763:             * 
1764:             * @param writer the filename to write to
1765:             * @param o the object to serialize as XML
1766:             * @throws Exception if something goes wrong with the parsing
1767:             */
1768:            public void write(Writer writer, Object o) throws Exception {
1769:                toXML(o).write(writer);
1770:            }
1771:
1772:            /**
1773:             * for testing only. if the first argument is a filename with ".xml"
1774:             * as extension it tries to generate an instance from the XML description
1775:             * and does a <code>toString()</code> of the generated object.
1776:             */
1777:            public static void main(String[] args) throws Exception {
1778:                if (args.length > 0) {
1779:                    // read xml and print
1780:                    if (args[0].toLowerCase().endsWith(".xml")) {
1781:                        System.out.println(new XMLSerialization().read(args[0])
1782:                                .toString());
1783:                    }
1784:                    // read binary and print generated XML
1785:                    else {
1786:                        // read
1787:                        FileInputStream fi = new FileInputStream(args[0]);
1788:                        ObjectInputStream oi = new ObjectInputStream(
1789:                                new BufferedInputStream(fi));
1790:                        Object o = oi.readObject();
1791:                        oi.close();
1792:                        // print to stdout
1793:                        //new XMLSerialization().write(System.out, o);
1794:                        new XMLSerialization().write(new BufferedOutputStream(
1795:                                new FileOutputStream(args[0] + ".xml")), o);
1796:                        // print to binary file
1797:                        FileOutputStream fo = new FileOutputStream(args[0]
1798:                                + ".exp");
1799:                        ObjectOutputStream oo = new ObjectOutputStream(
1800:                                new BufferedOutputStream(fo));
1801:                        oo.writeObject(o);
1802:                        oo.close();
1803:                    }
1804:                }
1805:            }
1806:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.