MentaContainer

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

package org.mentacontainer.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.mentacontainer.util.FindMethod;

class Component {
           
            private Class<? extends Object> klass;
           
            private Map<String, Object> props = null;
           
            private List<Object> initValues = null;
           
            private Constructor<? extends Object> constructor = null;
           
            private Map<String, Method> cache = null;
           
            private final boolean singleton;

            public Component(Class<? extends Object> klass, boolean singleton) {

                this.klass = klass;
               
                this.singleton = singleton;
            }
           
            public boolean isSingleton() { return singleton; }
           
            public void addProperty(String name, Object value) {
               
                if (props == null) {
                       
                    props = new HashMap<String, Object>();
                   
                    cache = new HashMap<String, Method>();
                }
               
                props.put(name, value);
            }
           
            public void addInitValue(Object value) {
               
                if (initValues == null) {
                       
                    initValues = new LinkedList<Object>();
                }
               
                initValues.add(value);
            }
           
            private Class<? extends Object>[] getClasses(List<Object> values) {
               
                Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()];
               
                Iterator<Object> iter = values.iterator();
               
                int index = 0;
               
                while(iter.hasNext()) {
                       
                    Object value = iter.next();
                   
                    if (value != null) {
                       
                        types[index++] = value.getClass();
                       
                    } else {
                       
                        types[index++] = null;
                    }
                }
               
                return types;
            }
           
            private Object [] getValues(List<Object> values) throws InstantiationException {
               
                Object [] array = new Object[values.size()];
               
                int index = 0;
               
                Iterator<Object> iter = values.iterator();
               
                while(iter.hasNext()) {
               
                        Object obj = iter.next();
                   
                        array[index++] = obj;
                }
               
                return array;
            }
           
                /*
                 * Use reflection to set a property in the bean
                 */

                private void setValue(Object bean, String name, Object value) throws InstantiationException {
               
                        try {
                                StringBuffer sb = new StringBuffer(30);
                                sb.append("set");
                                sb.append(name.substring(0,1).toUpperCase());
                                if (name.length() > 1) sb.append(name.substring(1));
                   
                    String methodName = sb.toString();
                   
                    if (!cache.containsKey(name)) {
                        Method m = null;
                        try {
                            m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() });
                        } catch(Exception e) {
                            // try primitive...
                            Class<? extends Object> primitive = getPrimitiveFrom(value);
                            if (primitive != null) {
                                try {
                                    m = klass.getMethod(methodName, new Class[] { primitive });
                                } catch(Exception ex) {
                                        // not found!
                                }
                            }
                           
                            if (m == null) {
                                throw new InstantiationException("Cannot find method or field for property: " + name);
                            }
                        }
                       
                        if (m != null) {
                            cache.put(name, m);
                            m.setAccessible(true);
                        }
                    }    

                    Method m = cache.get(name);
                    if (m != null) {
                        m.invoke(bean, new Object[] { value });
                    }                
                        } catch(Exception e) {
                                throw new InstantiationException("Error trying to set a property with reflection: " + name);
                        }
                }
           
            private static Class<? extends Object> getPrimitiveFrom(Object w) {
                if (w instanceof Boolean) { return Boolean.TYPE; }
                else if (w instanceof Byte) { return Byte.TYPE; }
                else if (w instanceof Short) { return Short.TYPE; }
                else if (w instanceof Character) { return Character.TYPE; }
                else if (w instanceof Integer) { return Integer.TYPE; }
                else if (w instanceof Long) { return Long.TYPE; }
                else if (w instanceof Float) { return Float.TYPE; }
                else if (w instanceof Double) { return Double.TYPE; }
                return null;
            }  
           
            public Object getInstance() throws InstantiationException {
                Object obj = null;
                if (initValues != null && initValues.size() > 0) {
                    if (constructor == null) {
                        try {
                            constructor = klass.getConstructor(getClasses(initValues));
                        } catch(Exception e) {
                            throw new InstantiationException("Cannot find a constructor for class: " + klass);
                        }
                    }
                    try {
                        obj = constructor.newInstance(getValues(initValues));
                    } catch(Exception e) {
                        throw new InstantiationException("Cannot create instance from constructor: " + constructor);
                    }
                } else {
                    try {
                        obj = klass.newInstance();
                    } catch(Exception e) {
                        throw new InstantiationException("Cannot create instance from class: " + klass);
                    }
                }
                if (props != null && props.size() > 0) {
                    Iterator<String> iter = props.keySet().iterator();
                    while(iter.hasNext()) {
                        String name = iter.next();
                        Object value = props.get(name);
                        setValue(obj, name, value);
                    }
                }
                return obj;
            }
        }