Logo
Distributed Genetic Programming Framework
print print

File org.jfree.xml.util.ObjectFactoryLoader.java

Here you can find all the information about the file org.jfree.xml.util.ObjectFactoryLoader.java. You may explore it here or download it onto your local disk.
/* ========================================================================
 * JCommon : a free general purpose class library for the Java(tm) platform
 * ========================================================================
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------------------
 * ObjectFactoryLoader.java
 * ------------------------
 * (C) Copyright 2002-2005, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   -;
 *
 * $Id: ObjectFactoryLoader.java,v 1.4 2005/10/18 13:33:53 mungady Exp $
 *
 * Changes
 * -------
 * 24-Sep-2003: Initial version
 *
 */


package org.jfree.xml.util;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;

import org.jfree.util.Log;
import org.jfree.xml.attributehandlers.AttributeHandler;

/**
 * The object factory loader loads the xml specification for the generic
 * handlers. The specification may be distributed over multiple files.
 * <p>
 * This class provides the model management for the reader and writer.
 * The instantiation of the handlers is done elsewhere.
 *
 * @author TM
 */

public class ObjectFactoryLoader extends AbstractModelReader implements ObjectFactory {

    /** Maps classes to GenericObjectFactory instances. */
    private HashMap objectMappings;
    
    /** Manual mappings. */
    private HashMap manualMappings;
    
    /** Multiplex mappings. */
    private HashMap multiplexMappings;

    /** The target class. */
    private Class target;
    
    /** The register name. */
    private String registerName;
    
    /** The property definition. */
    private ArrayList propertyDefinition;
    
    /** The attribute definition. */
    private ArrayList attributeDefinition;
    
    /** The constructor definition. */
    private ArrayList constructorDefinition;
    
    /** The lookup definitions. */
    private ArrayList lookupDefinitions;
    
    /** The ordered names. */
    private ArrayList orderedNames;

    /** The base class. */
    private String baseClass;
    
    /** The attribute name. */
    private String attributeName;
    
    /** The multiplex entries. */
    private ArrayList multiplexEntries;

    /**
     * Creates a new object factory loader for the given base file.
     *
     * @param resourceName the URL of the initial specification file.
     * 
     * @throws ObjectDescriptionException if the file could not be parsed.
     */

    public ObjectFactoryLoader(final URL resourceName) throws ObjectDescriptionException {
        this.objectMappings = new HashMap();
        this.manualMappings = new HashMap();
        this.multiplexMappings = new HashMap();
        parseXml(resourceName);
        rebuildSuperClasses();
    }

    private void rebuildSuperClasses() throws ObjectDescriptionException {
        this.propertyDefinition = new ArrayList();
        this.attributeDefinition = new ArrayList();
        this.constructorDefinition = new ArrayList();
        this.lookupDefinitions = new ArrayList();
        this.orderedNames = new ArrayList();

        final HashMap newObjectDescriptions = new HashMap();
        final Iterator it = this.objectMappings.keySet().iterator();
        while (it.hasNext()) {
            final Object key = it.next();
            final GenericObjectFactory gef = (GenericObjectFactory) this.objectMappings.get(key);
            performSuperClassUpdate(gef);

            final PropertyDefinition[] propertyDefs = (PropertyDefinition[])
            this.propertyDefinition.toArray(new PropertyDefinition[0]);
            final LookupDefinition[] lookupDefs = (LookupDefinition[])
            this.lookupDefinitions.toArray(new LookupDefinition[0]);
            final AttributeDefinition[] attribDefs = (AttributeDefinition[])
            this.attributeDefinition.toArray(new AttributeDefinition[0]);
            final ConstructorDefinition[] constructorDefs = (ConstructorDefinition[])
            this.constructorDefinition.toArray(new ConstructorDefinition[0]);
            final String[] orderedNamesDefs = (String[])
            this.orderedNames.toArray(new String[0]);

            final GenericObjectFactory objectFactory = new GenericObjectFactory
                (gef.getBaseClass(), gef.getRegisterName(), constructorDefs,
                    propertyDefs, lookupDefs, attribDefs, orderedNamesDefs);
            newObjectDescriptions.put(key, objectFactory);

            this.propertyDefinition.clear();
            this.attributeDefinition.clear();
            this.constructorDefinition.clear();
            this.lookupDefinitions.clear();
            this.orderedNames.clear();
        }

        this.objectMappings.clear();
        this.objectMappings = newObjectDescriptions;

        this.propertyDefinition = null;
        this.attributeDefinition = null;
        this.constructorDefinition = null;
        this.lookupDefinitions = null;
        this.orderedNames = null;
    }

    private void performSuperClassUpdate(final GenericObjectFactory gef) {
        // first handle the super classes, ...
        final Class superClass = gef.getBaseClass().getSuperclass();
        if (superClass != null && !superClass.equals(Object.class)) {
            final GenericObjectFactory superGef = (GenericObjectFactory) this.objectMappings.get(
                superClass
            );
            if (superGef != null) {
                performSuperClassUpdate(superGef);
            }
        }

        // and finally append all local properties ...
        this.propertyDefinition.addAll(Arrays.asList(gef.getPropertyDefinitions()));
        this.attributeDefinition.addAll(Arrays.asList(gef.getAttributeDefinitions()));
        this.constructorDefinition.addAll(Arrays.asList(gef.getConstructorDefinitions()));
        this.lookupDefinitions.addAll(Arrays.asList(gef.getLookupDefinitions()));
        this.orderedNames.addAll(Arrays.asList(gef.getOrderedPropertyNames()));
    }

    /**
     * Starts a object definition. The object definition collects all properties of
     * an bean-class and defines, which constructor should be used when creating the
     * class.
     *
     * @param className the class name of the defined object
     * @param register the (optional) register name, to lookup and reference the object later.
     * @param ignore  ignore?
     * 
     * @return true, if the definition was accepted, false otherwise.
     * @throws ObjectDescriptionException if an unexpected error occured.
     */

    protected boolean startObjectDefinition(final String className, final String register, final boolean ignore)
        throws ObjectDescriptionException {

        if (ignore) {
            return false;
        }
        this.target = loadClass(className);
        if (this.target == null) {
            Log.warn(new Log.SimpleMessage("Failed to load class ", className));
            return false;
        }
        this.registerName = register;
        this.propertyDefinition = new ArrayList();
        this.attributeDefinition = new ArrayList();
        this.constructorDefinition = new ArrayList();
        this.lookupDefinitions = new ArrayList();
        this.orderedNames = new ArrayList();
        return true;
    }

    /**
     * Handles an attribute definition. This method gets called after the object definition
     * was started. The method will be called for every defined attribute property.
     *
     * @param name the name of the property
     * @param attribName the xml-attribute name to use later.
     * @param handlerClass the attribute handler class.
     * @throws ObjectDescriptionException if an error occured.
     */

    protected void handleAttributeDefinition(final String name, final String attribName, final String handlerClass)
        throws ObjectDescriptionException {
        final AttributeHandler handler = loadAttributeHandler(handlerClass);
        this.orderedNames.add(name);
        this.attributeDefinition.add(new AttributeDefinition(name, attribName, handler));
    }

    /**
     * Handles an element definition. This method gets called after the object definition
     * was started. The method will be called for every defined element property. Element
     * properties are used to describe complex objects.
     *
     * @param name the name of the property
     * @param element the xml-tag name for the child element.
     * @throws ObjectDescriptionException if an error occurs.
     */

    protected void handleElementDefinition(final String name, final String element)
        throws ObjectDescriptionException {
        this.orderedNames.add(name);
        this.propertyDefinition.add(new PropertyDefinition(name, element));
    }

    /**
     * Handles an lookup definition. This method gets called after the object definition
     * was started. The method will be called for every defined lookup property. Lookup properties
     * reference previously created object using the object's registry name.
     *
     * @param name the property name of the base object
     * @param lookupKey the register key of the referenced object
     * @throws ObjectDescriptionException if an error occured.
     */

    protected void handleLookupDefinition(final String name, final String lookupKey)
        throws ObjectDescriptionException {
        final LookupDefinition ldef = new LookupDefinition(name, lookupKey);
        this.orderedNames.add(name);
        this.lookupDefinitions.add(ldef);
    }

    /**
     * Finializes the object definition.
     *
     * @throws ObjectDescriptionException if an error occures.
     */

    protected void endObjectDefinition()
        throws ObjectDescriptionException {

        final PropertyDefinition[] propertyDefs = (PropertyDefinition[])
        this.propertyDefinition.toArray(new PropertyDefinition[0]);
        final LookupDefinition[] lookupDefs = (LookupDefinition[])
        this.lookupDefinitions.toArray(new LookupDefinition[0]);
        final AttributeDefinition[] attribDefs = (AttributeDefinition[])
        this.attributeDefinition.toArray(new AttributeDefinition[0]);
        final ConstructorDefinition[] constructorDefs = (ConstructorDefinition[])
        this.constructorDefinition.toArray(new ConstructorDefinition[0]);
        final String[] orderedNamesDefs = (String[])
        this.orderedNames.toArray(new String[0]);

        final GenericObjectFactory objectFactory = new GenericObjectFactory
            (this.target, this.registerName, constructorDefs,
                propertyDefs, lookupDefs, attribDefs, orderedNamesDefs);
        this.objectMappings.put(this.target, objectFactory);
    }

    /**
     * Handles a constructor definition. Only one constructor can be defined for
     * a certain object type. The constructor will be filled using the given properties.
     *
     * @param propertyName the property name of the referenced local property
     * @param parameterClass the parameter class for the parameter.
     */

    protected void handleConstructorDefinition(final String propertyName, final String parameterClass) {
        final Class c = loadClass(parameterClass);
        this.orderedNames.add(propertyName);
        this.constructorDefinition.add(new ConstructorDefinition(propertyName, c));
    }

    /**
     * Handles a manual mapping definition. The manual mapping maps specific
     * read and write handlers to a given base class. Manual mappings always
     * override any other definition.
     *
     * @param className the base class name
     * @param readHandler the class name of the read handler
     * @param writeHandler the class name of the write handler
     * @return true, if the mapping was accepted, false otherwise.
     * @throws ObjectDescriptionException if an unexpected error occured.
     */

    protected boolean handleManualMapping(final String className, final String readHandler, final String writeHandler)
        throws ObjectDescriptionException {

        if (!this.manualMappings.containsKey(className)) {
            final Class loadedClass = loadClass(className);
            this.manualMappings.put(loadedClass, new ManualMappingDefinition
                (loadedClass, readHandler, writeHandler));
            return true;
        }
        return false;
    }

    /**
     * Starts a multiplex mapping. Multiplex mappings are used to define polymorphic
     * argument handlers. The mapper will collect all derived classes of the given
     * base class and will select the corresponding mapping based on the given type
     * attribute.
     *
     * @param className the base class name
     * @param typeAttr the xml-attribute name containing the mapping key
     */

    protected void startMultiplexMapping(final String className, final String typeAttr) {
        this.baseClass = className;
        this.attributeName = typeAttr;
        this.multiplexEntries = new ArrayList();
    }

    /**
     * Defines an entry for the multiplex mapping. The new entry will be activated
     * when the base mappers type attribute contains this <code>typename</code> and
     * will resolve to the handler for the given classname.
     *
     * @param typeName the type value for this mapping.
     * @param className the class name to which this mapping resolves.
     * @throws ObjectDescriptionException if an error occurs.
     */

    protected void handleMultiplexMapping(final String typeName, final String className)
        throws ObjectDescriptionException {
        this.multiplexEntries.add
            (new MultiplexMappingEntry(typeName, className));
    }

    /**
     * Finializes the multiplexer mapping.
     *
     * @throws ObjectDescriptionException if an error occurs.
     */

    protected void endMultiplexMapping() throws ObjectDescriptionException {
        final MultiplexMappingEntry[] mappings = (MultiplexMappingEntry[])
        this.multiplexEntries.toArray(new MultiplexMappingEntry[0]);
        final Class c = loadClass(this.baseClass);
        this.multiplexMappings.put(c,
            new MultiplexMappingDefinition(c, this.attributeName, mappings));
        this.multiplexEntries = null;
    }

    /**
     * Loads an instantiates the attribute handler specified by the given
     * class name.
     *
     * @param attribute the attribute handlers classname.
     * @return the created attribute handler instance
     * @throws ObjectDescriptionException if the handler could not be loaded.
     */

    private AttributeHandler loadAttributeHandler(final String attribute)
        throws ObjectDescriptionException {

        final Class c = loadClass(attribute);
        try {
            return (AttributeHandler) c.newInstance();
        }
        catch (Exception e) {
            throw new ObjectDescriptionException
                ("Invalid attribute handler specified: " + attribute);
        }
    }

    /**
     * Checks, whether the factory has a description for the given class.
     *
     * @param c the class to be handled by the factory.
     * @return true, if an description exists for the given class, false otherwise.
     */

    public boolean isGenericHandler(final Class c) {
        return this.objectMappings.containsKey(c);
    }

    /**
     * Returns a factory instance for the given class. The factory is independent
     * from all previously generated instances.
     *
     * @param c the class
     * @return the object factory.
     */

    public GenericObjectFactory getFactoryForClass(final Class c) {
        final GenericObjectFactory factory = (GenericObjectFactory) this.objectMappings.get(c);
        if (factory == null) {
            return null;
        }
        return factory.getInstance();
    }

    /**
     * Returns the manual mapping definition for the given class, or null, if
     * not manual definition exists.
     *
     * @param c the class for which to check the existence of the definition
     * @return the manual mapping definition or null.
     */

    public ManualMappingDefinition getManualMappingDefinition(final Class c) {
        return (ManualMappingDefinition) this.manualMappings.get(c);
    }

    /**
     * Returns the multiplex definition for the given class, or null, if no
     * such definition exists.
     *
     * @param c the class for which to check the existence of the multiplexer
     * @return the multiplexer for the class, or null if no multiplexer exists.
     */

    public MultiplexMappingDefinition getMultiplexDefinition(final Class c) {
        final MultiplexMappingDefinition definition = (MultiplexMappingDefinition)
        this.multiplexMappings.get(c);
        return definition;
    }

}

File Information:

file name:ObjectFactoryLoader.java
package:org.jfree.xml.util
qualified name:org.jfree.xml.util.ObjectFactoryLoader.java
file type:Java Source File
download location:download http://dgpf.sourceforge.net/source/org/jfree/xml/util/ObjectFactoryLoader.java
size:17.669 KB (18094 B)
uploaded: 2018-01-07 12:03:36 GMT+0000
last update: 2006-09-26 10:30:38 GMT+0000
last access: 2018-04-26 13:38:25 GMT+0000

statistics online since 2006-01-02.   RSS Feed
Contact us by sending an email to tweise@gmx.de to receive further information, to report errors, or to join our project.
All content on this site (http://dgpf.sourceforge.net/) is LGPL-licensed.
http://dgpf.sourceforge.net/scripts/source/source.php last modified at 2018-01-07 12:03:34 GMT+0000 served at 2018-04-26 13:38:25 GMT+0000.
Valid CSS Valid XHTML 1.1
Valid RSS SourceForge.net Logo