MentaContainer

Rev

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