    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     * AbstractObjectDescription.java
    029     * ------------------------------
    030     * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
    031     *
    032     * Original Author:  Thomas Morgner;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * $Id: AbstractObjectDescription.java,v 1.3 2005/11/14 10:58:37 mungady Exp $
    036     *
    037     * Changes (from 19-Feb-2003)
    038     * -------------------------
    039     * 19-Feb-2003 : Added standard header and Javadocs (DG);
    040     * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon
    041     *
    042     */
    043
    044    package org.jfree.xml.factory.objects;
    045
    046    import java.util.ArrayList;
    047    import java.util.Collections;
    048    import java.util.HashMap;
    049    import java.util.Iterator;
    050
    051    import org.jfree.util.Configuration;
    052    import org.jfree.util.Log;
    053    import org.jfree.util.ReadOnlyIterator;
    054
    055    /**
    056     * An abstract base class for object descriptions.
    057     *
    058     * @author Thomas Morgner.
    059     */
    060    public abstract class AbstractObjectDescription implements ObjectDescription, Cloneable {
    061
    062        /** The class. */
    063        private Class className;
    064
    065        /** Storage for parameters. */
    066        private HashMap parameters;
    067
    068        /** Storage for parameter definitions. */
    069        private HashMap parameterDefs;
    070
    071        /** The configuration for the object description. */
    072        private Configuration config;
    073
    074        /**
    075         * Creates a new object description.
    076         *
    077         * @param className  the class.
    078         */
    079        public AbstractObjectDescription(final Class className) {
    080            this.className = className;
    081            this.parameters = new HashMap();
    082            this.parameterDefs = new HashMap();
    083        }
    084
    085        /**
    086         * Returns a parameter class.
    087         *
    088         * @param name  the parameter definition.
    089         *
    090         * @return The class.
    091         */
    092        public Class getParameterDefinition(final String name) {
    093            return (Class) this.parameterDefs.get(name);
    094        }
    095
    096        /**
    097         * Sets the class for a parameter.
    098         *
    099         * @param name  the parameter name.
    100         * @param obj  the parameter class.
    101         */
    102        public void setParameterDefinition(final String name, final Class obj) {
    103            if (obj == null) {
    104                this.parameterDefs.remove(name);
    105            }
    106            else {
    107                this.parameterDefs.put(name, obj);
    108            }
    109        }
    110
    111        /**
    112         * Converts primitives to corresponding object class.
    113         *
    114         * @param obj  the class.
    115         *
    116         * @return The class.
    117         */
    118        public static Class convertPrimitiveClass(final Class obj) {
    119            if (!obj.isPrimitive()) {
    120                return obj;
    121            }
    122            if (obj == Boolean.TYPE) {
    123                return Boolean.class;
    124            }
    125            if (obj == Byte.TYPE) {
    126                return Byte.class;
    127            }
    128            if (obj == Character.TYPE) {
    129                return Character.class;
    130            }
    131            if (obj == Short.TYPE) {
    132                return Short.class;
    133            }
    134            if (obj == Integer.TYPE) {
    135                return Integer.class;
    136            }
    137            if (obj == Long.TYPE) {
    138                return Long.class;
    139            }
    140            if (obj == Float.TYPE) {
    141                return Float.class;
    142            }
    143            if (obj == Double.TYPE) {
    144                return Double.class;
    145            }
    146            throw new IllegalArgumentException("Class 'void' is not allowed here");
    147        }
    148
    149        /**
    150         * Sets a parameter.
    151         *
    152         * @param name  the name.
    153         * @param value  the value.
    154         */
    155        public void setParameter(final String name, final Object value) {
    156            if (getParameterDefinition(name) == null) {
    157                throw new IllegalArgumentException("No such Parameter defined: " + name
    158                    + " in class " + getObjectClass());
    159            }
    160            final Class parameterClass = convertPrimitiveClass(getParameterDefinition(name));
    161            if (!parameterClass.isAssignableFrom(value.getClass())) {
    162                throw new ClassCastException("In Object " + getObjectClass()
    163                    + ": Value is not assignable: " + value.getClass()
    164                    + " is not assignable from " + parameterClass);
    165            }
    166            this.parameters.put(name, value);
    167        }
    168
    169        /**
    170         * Returns an iterator for the parameter names.
    171         *
    172         * @return The iterator.
    173         */
    174        public synchronized Iterator getParameterNames() {
    175            final ArrayList parameterNames = new ArrayList(this.parameterDefs.keySet());
    176            Collections.sort(parameterNames);
    177            return new ReadOnlyIterator (parameterNames.iterator());
    178        }
    179
    180        /**
    181         * Returns an iterator for the parameter names.
    182         *
    183         * @return The iterator.
    184         */
    185        protected Iterator getDefinedParameterNames() {
    186            return new ReadOnlyIterator (this.parameters.keySet().iterator());
    187        }
    188
    189        /**
    190         * Returns a parameter value.
    191         *
    192         * @param name  the parameter name.
    193         *
    194         * @return The parameter value.
    195         */
    196        public Object getParameter(final String name) {
    197            return this.parameters.get(name);
    198        }
    199
    200        /**
    201         * Returns the class for the object.
    202         *
    203         * @return The class.
    204         */
    205        public Class getObjectClass() {
    206            return this.className;
    207        }
    208
    209        /**
    210         * Returns a cloned instance of the object description. The contents
    211         * of the parameter objects collection are cloned too, so that any
    212         * already defined parameter value is copied to the new instance.
    213         * <p>
    214         * Parameter definitions are not cloned, as they are considered read-only.
    215         * <p>
    216         * The newly instantiated object description is not configured. If it
    217         * need to be configured, then you have to call configure on it.
    218         *
    219         * @return A cloned instance.
    220         */
    221        public ObjectDescription getInstance() {
    222            try {
    223                final AbstractObjectDescription c = (AbstractObjectDescription) super.clone();
    224                c.parameters = (HashMap) this.parameters.clone();
    225                return c;
    226            }
    227            catch (Exception e) {
    228                Log.error("Should not happen: Clone Error: ", e);
    229                return null;
    230            }
    231        }
    232
    233
    234        /**
    235         * Returns a cloned instance of the object description. The contents
    236         * of the parameter objects collection are cloned too, so that any
    237         * already defined parameter value is copied to the new instance.
    238         * <p>
    239         * Parameter definitions are not cloned, as they are considered read-only.
    240         * <p>
    241         * The newly instantiated object description is not configured. If it
    242         * need to be configured, then you have to call configure on it.
    243         *
    244         * @return A cloned instance.
    245         */
    246        public ObjectDescription getUnconfiguredInstance() {
    247            try {
    248                final AbstractObjectDescription c = (AbstractObjectDescription) super.clone();
    249                c.parameters = (HashMap) this.parameters.clone();
    250                c.config = null;
    251                return c;
    252            }
    253            catch (Exception e) {
    254                Log.error("Should not happen: Clone Error: ", e);
    255                return null;
    256            }
    257        }
    258
    259        /**
    260         * Configures this factory. The configuration contains several keys and
    261         * their defined values. The given reference to the configuration object
    262         * will remain valid until the report parsing or writing ends.
    263         * <p>
    264         * The configuration contents may change during the reporting.
    265         *
    266         * @param config the configuration, never null
    267         */
    268        public void configure(final Configuration config) {
    269            if (config == null) {
    270                throw new NullPointerException("The given configuration is null");
    271            }
    272            this.config = config;
    273        }
    274
    275        /**
    276         * Returns the configuration for that object description.
    277         *
    278         * @return the configuration or null, if not yet set.
    279         */
    280        public Configuration getConfig() {
    281            return this.config;
    282        }
    283
    284        /**
    285         * Tests for equality.
    286         *
    287         * @param o  the object to test.
    288         *
    289         * @return A boolean.
    290         */
    291        public boolean equals(final Object o) {
    292            if (this == o) {
    293                return true;
    294            }
    295            if (!(o instanceof AbstractObjectDescription)) {
    296                return false;
    297            }
    298
    299            final AbstractObjectDescription abstractObjectDescription = (AbstractObjectDescription) o;
    300
    301            if (!this.className.equals(abstractObjectDescription.className)) {
    302                return false;
    303            }
    304
    305            return true;
    306        }
    307
    308        /**
    309         * Returns a hash code for the object.
    310         *
    311         * @return The hash code.
    312         */
    313        public int hashCode() {
    314            return this.className.hashCode();
    315        }
    316    }