MentaContainer

Rev

Rev 39 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 soliveira 1
package org.mentacontainer.impl;
2
 
3
import java.lang.reflect.Constructor;
4
import java.lang.reflect.Method;
5
import java.util.HashMap;
6
import java.util.Iterator;
7
import java.util.LinkedList;
8
import java.util.List;
9
import java.util.Map;
10
 
20 soliveira 11
import org.mentacontainer.Component;
2 soliveira 12
import org.mentacontainer.util.FindMethod;
13
 
20 soliveira 14
/**
15
 * A simple implementation of the Component interface.
16
 *
17
 * @author sergio.oliveira.jr@gmail.com
18
 */
19
public class MentaComponent implements Component {
20
 
21
            private final Class<? extends Object> klass;
2 soliveira 22
 
23
            private Map<String, Object> props = null;
24
 
25
            private List<Object> initValues = null;
26
 
27
            private Constructor<? extends Object> constructor = null;
28
 
29
            private Map<String, Method> cache = null;
30
 
31
            private final boolean singleton;
23 soliveira 32
 
33
            private Object singletonValue = null;
2 soliveira 34
 
39 soliveira 35
            public MentaComponent(Class<? extends Object> klass, boolean singleton) {
20 soliveira 36
 
2 soliveira 37
                this.klass = klass;
38
 
39
                this.singleton = singleton;
40
            }
41
 
39 soliveira 42
            public MentaComponent(Class<? extends Object> klass) {
20 soliveira 43
 
39 soliveira 44
                this(klass, false);
20 soliveira 45
            }
46
 
2 soliveira 47
            public boolean isSingleton() { return singleton; }
48
 
20 soliveira 49
            public Component addProperty(String name, Object value) {
2 soliveira 50
 
51
                if (props == null) {
52
 
53
                    props = new HashMap<String, Object>();
54
 
55
                    cache = new HashMap<String, Method>();
56
                }
57
 
58
                props.put(name, value);
20 soliveira 59
 
60
                return this;
2 soliveira 61
            }
62
 
20 soliveira 63
            public Component addInitValue(Object value) {
2 soliveira 64
 
65
                if (initValues == null) {
66
 
67
                    initValues = new LinkedList<Object>();
68
                }
69
 
70
                initValues.add(value);
20 soliveira 71
 
72
                return this;
2 soliveira 73
            }
74
 
75
            private Class<? extends Object>[] getClasses(List<Object> values) {
76
 
77
                Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()];
78
 
79
                Iterator<Object> iter = values.iterator();
80
 
81
                int index = 0;
82
 
83
                while(iter.hasNext()) {
84
 
85
                    Object value = iter.next();
86
 
87
                    if (value != null) {
88
 
89
                        types[index++] = value.getClass();
90
 
91
                    } else {
92
 
93
                        types[index++] = null;
94
                    }
95
                }
96
 
97
                return types;
98
            }
99
 
100
            private Object [] getValues(List<Object> values) throws InstantiationException {
101
 
102
                Object [] array = new Object[values.size()];
103
 
104
                int index = 0;
105
 
106
                Iterator<Object> iter = values.iterator();
107
 
108
                while(iter.hasNext()) {
109
 
110
                        Object obj = iter.next();
111
 
112
                        array[index++] = obj;
113
                }
114
 
115
                return array;
116
            }
117
 
118
                /*
119
                 * Use reflection to set a property in the bean
120
                 */
40 soliveira 121
                private void setValue(Object bean, String name, Object value) {
2 soliveira 122
 
123
                        try {
20 soliveira 124
 
2 soliveira 125
                                StringBuffer sb = new StringBuffer(30);
126
                                sb.append("set");
127
                                sb.append(name.substring(0,1).toUpperCase());
20 soliveira 128
 
2 soliveira 129
                                if (name.length() > 1) sb.append(name.substring(1));
130
 
131
                    String methodName = sb.toString();
132
 
133
                    if (!cache.containsKey(name)) {
20 soliveira 134
 
2 soliveira 135
                        Method m = null;
20 soliveira 136
 
2 soliveira 137
                        try {
20 soliveira 138
 
2 soliveira 139
                            m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() });
20 soliveira 140
 
2 soliveira 141
                        } catch(Exception e) {
20 soliveira 142
 
2 soliveira 143
                            // try primitive...
20 soliveira 144
 
2 soliveira 145
                            Class<? extends Object> primitive = getPrimitiveFrom(value);
20 soliveira 146
 
2 soliveira 147
                            if (primitive != null) {
20 soliveira 148
 
2 soliveira 149
                                try {
20 soliveira 150
 
2 soliveira 151
                                    m = klass.getMethod(methodName, new Class[] { primitive });
20 soliveira 152
 
2 soliveira 153
                                } catch(Exception ex) {
154
                                        // not found!
155
                                }
156
                            }
157
 
158
                            if (m == null) {
20 soliveira 159
 
2 soliveira 160
                                throw new InstantiationException("Cannot find method or field for property: " + name);
161
                            }
162
                        }
163
 
164
                        if (m != null) {
20 soliveira 165
 
2 soliveira 166
                            cache.put(name, m);
20 soliveira 167
 
2 soliveira 168
                            m.setAccessible(true);
169
                        }
170
                    }    
171
 
172
                    Method m = cache.get(name);
20 soliveira 173
 
2 soliveira 174
                    if (m != null) {
20 soliveira 175
 
2 soliveira 176
                        m.invoke(bean, new Object[] { value });
177
                    }                
20 soliveira 178
 
2 soliveira 179
                        } catch(Exception e) {
20 soliveira 180
 
40 soliveira 181
                                throw new RuntimeException("Error trying to set a property with reflection: " + name, e);
2 soliveira 182
                        }
183
                }
184
 
185
            private static Class<? extends Object> getPrimitiveFrom(Object w) {
186
                if (w instanceof Boolean) { return Boolean.TYPE; }
187
                else if (w instanceof Byte) { return Byte.TYPE; }
188
                else if (w instanceof Short) { return Short.TYPE; }
189
                else if (w instanceof Character) { return Character.TYPE; }
190
                else if (w instanceof Integer) { return Integer.TYPE; }
191
                else if (w instanceof Long) { return Long.TYPE; }
192
                else if (w instanceof Float) { return Float.TYPE; }
193
                else if (w instanceof Double) { return Double.TYPE; }
194
                return null;
195
            }  
196
 
40 soliveira 197
            public Object getInstance()  {
20 soliveira 198
 
23 soliveira 199
                if (singleton && singletonValue != null) return singletonValue;
200
 
2 soliveira 201
                Object obj = null;
20 soliveira 202
 
2 soliveira 203
                if (initValues != null && initValues.size() > 0) {
20 soliveira 204
 
2 soliveira 205
                    if (constructor == null) {
20 soliveira 206
 
2 soliveira 207
                        try {
20 soliveira 208
 
2 soliveira 209
                            constructor = klass.getConstructor(getClasses(initValues));
20 soliveira 210
 
2 soliveira 211
                        } catch(Exception e) {
20 soliveira 212
 
40 soliveira 213
                            throw new RuntimeException("Cannot find a constructor for class: " + klass, e);
2 soliveira 214
                        }
215
                    }
20 soliveira 216
 
2 soliveira 217
                    try {
20 soliveira 218
 
2 soliveira 219
                        obj = constructor.newInstance(getValues(initValues));
20 soliveira 220
 
2 soliveira 221
                    } catch(Exception e) {
20 soliveira 222
 
40 soliveira 223
                        throw new RuntimeException("Cannot create instance from constructor: " + constructor, e);
2 soliveira 224
                    }
20 soliveira 225
 
2 soliveira 226
                } else {
20 soliveira 227
 
2 soliveira 228
                    try {
20 soliveira 229
 
2 soliveira 230
                        obj = klass.newInstance();
20 soliveira 231
 
2 soliveira 232
                    } catch(Exception e) {
20 soliveira 233
 
40 soliveira 234
                        throw new RuntimeException("Cannot create instance from class: " + klass, e);
2 soliveira 235
                    }
236
                }
20 soliveira 237
 
2 soliveira 238
                if (props != null && props.size() > 0) {
20 soliveira 239
 
2 soliveira 240
                    Iterator<String> iter = props.keySet().iterator();
20 soliveira 241
 
2 soliveira 242
                    while(iter.hasNext()) {
20 soliveira 243
 
2 soliveira 244
                        String name = iter.next();
20 soliveira 245
 
2 soliveira 246
                        Object value = props.get(name);
20 soliveira 247
 
2 soliveira 248
                        setValue(obj, name, value);
249
                    }
250
                }
20 soliveira 251
 
23 soliveira 252
                if (obj != null && singleton) singletonValue = obj;
253
 
2 soliveira 254
                return obj;
255
            }
256
        }