001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022package org.biojavax;
023
024import java.lang.reflect.Constructor;
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.Iterator;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031
032
033/**
034 * Creates objects and returns them, and stores them in an internal
035 * map of singletons for reference. Takes up a lot of memory!
036 * @author Richard Holland
037 * @since 1.5
038 */
039public class SimpleRichObjectBuilder implements RichObjectBuilder {
040    
041    private static Map objects = new HashMap();
042    
043    /**
044     * {@inheritDoc}
045     * Instantiates and returns objects, that's all there is to it.
046     */
047    public Object buildObject(Class clazz, List paramsList) {
048        // put the class into the hashmap if not there already
049        if (!objects.containsKey(clazz)) objects.put(clazz,new HashMap());
050        Map contents = (Map)objects.get(clazz);
051        // convert the params list to remove nulls as we can't process those.
052        List ourParamsList = new ArrayList(paramsList);
053        for (Iterator i = ourParamsList.iterator(); i.hasNext(); ) 
054                if (i.next()==null) i.remove();
055        // return the constructed object from the hashmap if there already
056        if (contents.containsKey(ourParamsList)) return contents.get(ourParamsList);
057        // otherwise build it.
058        try {
059            // Load the class
060            Class[] types = new Class[ourParamsList.size()];
061            // Find its constructor with given params
062            for (int i = 0; i < ourParamsList.size(); i++) {
063                if (ourParamsList.get(i) instanceof Set) types[i] = Set.class;
064                else if (ourParamsList.get(i) instanceof Map) types[i] = Map.class;
065                else if (ourParamsList.get(i) instanceof List) types[i] = List.class;
066                else types[i] = ourParamsList.get(i).getClass();
067            }
068            Constructor c = clazz.getConstructor(types);
069            // Instantiate it with the parameters
070            Object o = c.newInstance(ourParamsList.toArray());
071            // store it for later in the singleton map
072            contents.put(ourParamsList, o);
073            // return it
074            return o;
075        } catch (Exception e) {
076            StringBuffer paramsstuff = new StringBuffer();
077            paramsstuff.append(clazz);
078            paramsstuff.append("(");
079            for (int i = 0; i < ourParamsList.size(); i++) {
080                if (i>0) paramsstuff.append(",");
081                paramsstuff.append(ourParamsList.get(i).getClass());
082            }
083            paramsstuff.append(")");
084            IllegalArgumentException ie = new IllegalArgumentException("Could not find constructor for "+paramsstuff);
085            ie.initCause(e);
086            throw ie;
087        }
088    }
089    
090}