    001    /* ========================================================================
    002     * JCommon : a free general purpose class library for the Java(tm) platform
    003     * ========================================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jcommon/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * -----------------------
    028     * GenericReadHandler.java
    029     * -----------------------
    030     * (C)opyright 2003, by Thomas Morgner and Contributors.
    031     *
    032     * Original Author:  Thomas Morgner;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * $Id: GenericReadHandler.java,v 1.5 2005/10/18 13:33:32 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 23-Sep-2003 : Initial version
    040     *
    041     */
    042
    043    package org.jfree.xml.parser.coretypes;
    044
    045    import java.util.ArrayList;
    046    import java.util.HashMap;
    047
    048    import org.jfree.util.Log;
    049    import org.jfree.xml.parser.AbstractXmlReadHandler;
    050    import org.jfree.xml.parser.RootXmlReadHandler;
    051    import org.jfree.xml.parser.XmlReadHandler;
    052    import org.jfree.xml.parser.XmlReaderException;
    053    import org.jfree.xml.util.AttributeDefinition;
    054    import org.jfree.xml.util.ConstructorDefinition;
    055    import org.jfree.xml.util.GenericObjectFactory;
    056    import org.jfree.xml.util.LookupDefinition;
    057    import org.jfree.xml.util.ObjectDescriptionException;
    058    import org.jfree.xml.util.PropertyDefinition;
    059    import org.xml.sax.Attributes;
    060    import org.xml.sax.SAXException;
    061
    062    /**
    063     * A SAX handler for reading a generic object from an XML element.
    064     */
    065    public class GenericReadHandler extends AbstractXmlReadHandler {
    066
    067        /** The object under construction. */
    068        private Object object;
    069
    070        /** The generic object factory. */
    071        private GenericObjectFactory objectFactory;
    072
    073        /** The object reference handlers. */
    074        private ArrayList objectRefHandlers;
    075
    076        /** The created handler. */
    077        private HashMap createdHandler;
    078
    079        /**
    080         * Creates a new handler.
    081         *
    082         * @param factory  the generic object factory.
    083         */
    084        public GenericReadHandler(final GenericObjectFactory factory) {
    085            this.createdHandler = new HashMap();
    086            this.objectRefHandlers = new ArrayList();
    087            this.objectFactory = factory;
    088        }
    089
    090        /**
    091         * Called at the start of parsing.
    092         *
    093         * @param attrs  the attributes.
    094         *
    095         * @throws SAXException if there is a parsing error.
    096         */
    097        protected void startParsing(final Attributes attrs) throws SAXException {
    098
    099            try {
    100                final AttributeDefinition[] attribs = this.objectFactory.getAttributeDefinitions();
    101                for (int i = 0; i < attribs.length; i++) {
    102                    final AttributeDefinition attrDef = attribs[i];
    103                    final String value = attrs.getValue(attrDef.getAttributeName());
    104                    if (value == null) {
    105                        continue;
    106                    }
    107                    final Object o = attrDef.getHandler().toPropertyValue(value);
    108                    this.objectFactory.setProperty(attrDef.getPropertyName(), o);
    109                }
    110            }
    111            catch (ObjectDescriptionException ode) {
    112                throw new SAXException(ode);
    113            }
    114        }
    115
    116        /**
    117         * Returns the child handler.
    118         *
    119         * @param tagName  the tag name.
    120         * @param atts  the attributes.
    121         *
    122         * @return The handler.
    123         *
    124         * @throws SAXException if there is a parsing problem.
    125         */
    126        protected XmlReadHandler getHandlerForChild(final String tagName, final Attributes atts)
    127            throws SAXException {
    128            try {
    129                if (tagName.equals("objectRef")) {
    130                    // store them all and copy the properties later when the object is created
    131                    final XmlReadHandler handler = new ObjectRefHandler();
    132                    this.objectRefHandlers.add(handler);
    133                    return handler;
    134                }
    135                final XmlReadHandler handler = getRootHandler().createHandler
    136                    (this.objectFactory.getTypeForTagName(tagName), tagName, atts);
    137                if (handler != null) {
    138                    this.createdHandler.put(tagName, handler);
    139                }
    140                // will throw exception if handler is null...
    141                return handler;
    142            }
    143            catch (ObjectDescriptionException ode) {
    144                Log.debug ("Failed to get handler for child: ", ode);
    145                throw new SAXException(ode);
    146            }
    147        }
    148
    149        /**
    150         * Returns the object.
    151         *
    152         * @return The object.
    153         *
    154         * @throws XmlReaderException ???
    155         */
    156        public Object getObject() throws XmlReaderException {
    157
    158            if (this.object != null) {
    159                return this.object;
    160            }
    161            final RootXmlReadHandler rootHandler = getRootHandler();
    162            try {
    163                for (int i = 0; i < this.objectRefHandlers.size(); i++) {
    164                    final ObjectRefHandler handler = (ObjectRefHandler) this.objectRefHandlers.get(i);
    165                    this.objectFactory.setProperty(handler.getPropertyName(), handler.getObject());
    166                }
    167
    168                final ArrayList lookups = new ArrayList();
    169                final LookupDefinition[] lookupDefs = this.objectFactory.getLookupDefinitions();
    170                for (int i = 0; i < lookupDefs.length; i++) {
    171                    final LookupDefinition ldef = lookupDefs[i];
    172                    lookups.add(ldef.getPropertyName());
    173                    Log.debug ("lookup object: " + ldef.getPropertyName());
    174
    175                    final Object value = rootHandler.getHelperObject(ldef.getRegistryKey());
    176                    if (value == null) {
    177                        // todo may or may not be fatal -> define it in the xml?
    178                        Log.warn ("Failed to lookup object: " + value);
    179                    }
    180                    else {
    181                        this.objectFactory.setProperty(ldef.getPropertyName(), value);
    182                    }
    183                }
    184
    185                final ConstructorDefinition[] conDefs = this.objectFactory.getConstructorDefinitions();
    186                for (int i = 0; i < conDefs.length; i++) {
    187                    final ConstructorDefinition cDef = conDefs[i];
    188                    // if this is a lookup, then ignore
    189                    if (lookups.contains(cDef.getPropertyName())) {
    190                        continue;
    191                    }
    192                    if (this.objectFactory.isPropertyDefinition(cDef.getPropertyName())) {
    193                        final PropertyDefinition pd = this.objectFactory.getPropertyDefinitionByPropertyName(
    194                            cDef.getPropertyName()
    195                        );
    196                        final XmlReadHandler handler = (XmlReadHandler) this.createdHandler.get(
    197                            pd.getElementName()
    198                        );
    199                        if (handler != null) {
    200                            this.objectFactory.setProperty(pd.getPropertyName(), handler.getObject());
    201                        }
    202                    }
    203                    // hoping that the attribute is set ..
    204                }
    205
    206                this.object = this.objectFactory.createObject();
    207                Object oldValue = null;
    208                if (this.objectFactory.getRegisterName() != null) {
    209                    oldValue = rootHandler.getHelperObject(this.objectFactory.getRegisterName());
    210                    rootHandler.setHelperObject(this.objectFactory.getRegisterName(), this.object);
    211                }
    212
    213                final PropertyDefinition[] propertyDefs = this.objectFactory.getPropertyDefinitions();
    214                for (int i = 0; i < propertyDefs.length; i++) {
    215                    final PropertyDefinition pdef = propertyDefs[i];
    216                    final XmlReadHandler handler = (XmlReadHandler) this.createdHandler.get(
    217                        pdef.getElementName()
    218                    );
    219                    if (handler == null) {
    220                        continue;
    221                    }
    222                    this.objectFactory.setProperty(pdef.getPropertyName(), handler.getObject());
    223                }
    224
    225                this.objectFactory.writeObjectProperties(this.object);
    226
    227                if (this.objectFactory.getRegisterName() != null) {
    228                    rootHandler.setHelperObject(this.objectFactory.getRegisterName(), oldValue);
    229                }
    230            }
    231            catch (ObjectDescriptionException ode) {
    232                Log.error ("Unable to create object.", ode);
    233                throw new XmlReaderException("Unable to create object.", ode);
    234            }
    235            return this.object;
    236        }
    237
    238    }