EMMA Coverage Report (generated Tue Feb 12 22:23:49 ICT 2008)
[all classes][net.sourceforge.hiveutils.service.impl]

COVERAGE SUMMARY FOR SOURCE FILE [ObjectBuilderImpl.java]

nameclass, %method, %block, %line, %
ObjectBuilderImpl.java100% (2/2)79%  (11/14)81%  (340/418)82%  (71.2/87)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ObjectBuilderImpl$CachedObjectKey100% (1/1)100% (3/3)68%  (75/110)69%  (15.8/23)
equals (Object): boolean 100% (1/1)44%  (28/63)44%  (5.8/13)
ObjectBuilderImpl$CachedObjectKey (String, Object []): void 100% (1/1)100% (44/44)100% (9/9)
hashCode (): int 100% (1/1)100% (3/3)100% (1/1)
     
class ObjectBuilderImpl100% (1/1)73%  (8/11)86%  (265/308)87%  (55.4/64)
addObjectBuilderListener (ObjectBuilderListener): void 0%   (0/1)0%   (0/6)0%   (0/2)
get (String, Object []): Object 0%   (0/1)0%   (0/9)0%   (0/1)
removeObjectBuilderListener (ObjectBuilderListener): void 0%   (0/1)0%   (0/6)0%   (0/2)
fireObjectCreated (String, Object): void 100% (1/1)47%  (8/17)36%  (1.4/4)
injectConstructor (ObjectContribution, Object []): Object 100% (1/1)87%  (84/97)95%  (19/20)
ObjectBuilderImpl (Log, Map, Translator, EventLinker): void 100% (1/1)100% (25/25)100% (8/8)
addEventListener (Object, InjectObjectInformation, String): void 100% (1/1)100% (11/11)100% (2/2)
create (String, Object []): Object 100% (1/1)100% (79/79)100% (15/15)
getObject (InjectObjectInformation): Object 100% (1/1)100% (12/12)100% (1/1)
injectListeners (Object, ObjectContribution): void 100% (1/1)100% (20/20)100% (4/4)
injectSetters (Object, ObjectContribution): void 100% (1/1)100% (26/26)100% (5/5)

1//  Copyright 2004-2007 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14 
15package net.sourceforge.hiveutils.service.impl;
16 
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Map;
22 
23import org.apache.commons.logging.Log;
24import org.apache.hivemind.ApplicationRuntimeException;
25import org.apache.hivemind.schema.Translator;
26import org.apache.hivemind.service.EventLinker;
27import org.apache.hivemind.util.ConstructorUtils;
28import org.apache.hivemind.util.PropertyUtils;
29 
30import net.sourceforge.hiveutils.service.ObjectBuilder;
31import net.sourceforge.hiveutils.service.ObjectBuilderListener;
32 
33/**
34 * Implementation of the <code>ObjectBuilder</code> service.
35 *
36 * @author Jean-Francois Poilpret
37 */
38public class ObjectBuilderImpl implements ObjectBuilder
39{
40        public ObjectBuilderImpl(Log                                                                logger,
41                                 Map<String, ObjectContribution>        config, 
42                                 Translator                                                        objectTranslator,
43                                 EventLinker                                                linker)
44        {
45                _logger = logger;
46                _linker = linker;
47                _objectTranslator = objectTranslator;
48                _config = config;
49 
50                _cache = new HashMap<CachedObjectKey, Object>();
51                _listeners = new ArrayList<ObjectBuilderListener>();
52 
53                /*
54                List objectsToLoad = new ArrayList();
55                Iterator i = config.values().iterator();
56                while (i.hasNext())
57                {
58                        ObjectContribution contrib = (ObjectContribution) i.next();
59                        if (contrib.isEagerLoad())
60                        {
61                                contrib.setCached(true);
62                                objectsToLoad.add(contrib.getName());
63                        }
64                }
65                // Create eager-loaded objects (#### bug here? why? temporarily comment out)
66                i = objectsToLoad.iterator();
67                while (i.hasNext())
68                {
69                        //#### Should we catch all exceptions here?
70                        create((String) i.next());
71                }
72                */
73        }
74        
75        synchronized public void        addObjectBuilderListener(ObjectBuilderListener listener)
76        {
77                _listeners.add(listener);
78        }
79        
80        synchronized public void        removeObjectBuilderListener(ObjectBuilderListener listener)
81        {
82                _listeners.remove(listener);
83        }
84        
85        synchronized private void        fireObjectCreated(String name, Object object)
86        {
87                for (ObjectBuilderListener listener: _listeners)
88                {
89                        listener.objectCreated(name, object);
90                }
91        }
92 
93        @SuppressWarnings("unchecked")
94        public<T> T get(String name, Object... args)
95        {
96                return (T) _cache.get(new CachedObjectKey(name, args));
97        }
98        
99        @SuppressWarnings("unchecked")
100        public<T> T create(String        name, Object... userArgs)
101        {
102                // First find if the object is in the cache
103                T object = (T) _cache.get(new CachedObjectKey(name, userArgs));
104                if (object != null)
105                {
106                        return object;
107                }
108 
109                // Now find if there is a configuration for it
110                ObjectContribution contrib = _config.get(name);
111                if (contrib == null)
112                {
113                        _logger.info("create() has no contribution for object <" + name + ">");
114                        return null;
115                }
116 
117                // Build the object with constructor injection first
118                object = (T) injectConstructor(contrib, userArgs);
119 
120                // Then add setter injection
121                injectSetters(object, contrib);
122                
123                // Finally add listeners
124                injectListeners(object, contrib);
125                
126                if (contrib.isCached())
127                {
128                        _cache.put(new CachedObjectKey(name, userArgs), object);
129                }
130 
131                _logger.debug("create() just created object: " + name);
132                fireObjectCreated(name, object);
133                return object;
134        }
135 
136        private Object injectConstructor(ObjectContribution contrib, Object[] userArgs)
137        {
138                // Build the object with constructor injection first
139                String name = contrib.getName();
140                List ctorArgs = contrib.getConstructorInjections();
141                Object[] args = new Object[ctorArgs.size()];
142                Iterator i = ctorArgs.iterator();
143                int j = 0;
144                int k = 0;
145                while (i.hasNext())
146                {
147                        InjectObjectInformation inject = (InjectObjectInformation) i.next();
148                        if (inject != null)
149                        {
150                                args[j++] = getObject(inject);
151                        }
152                        else if (k < userArgs.length)
153                        {
154                                args[j++] = userArgs[k++];
155                        }
156                        else
157                        {
158                                _logger.error("create() has not enough user arguments for object <" +
159                                              name + ">");
160                                throw new ApplicationRuntimeException(
161                                        "create() has not enough user arguments for object <" + name + ">");
162                        }
163                }
164                if (k != userArgs.length)
165                {
166                        _logger.info("Too many user arguments passed to create() for object <" + 
167                                     name + ">");
168                }
169                return ConstructorUtils.invokeConstructor(contrib.getObjectClass(), args);
170        }
171        
172        private void        injectSetters(Object object, ObjectContribution contrib)
173        {
174                // Then add setter injection
175                Map<String, InjectObjectInformation> setters = contrib.getSetterInjections();
176                for (Map.Entry<String, InjectObjectInformation> entry: setters.entrySet())
177                {
178                        PropertyUtils.write(object, entry.getKey(), getObject(entry.getValue()));
179                }
180        }
181        
182        public void                injectListeners(Object object, ObjectContribution contrib)
183        {
184                for (ListenerContribution listener: contrib.getListeners())
185                {
186                        addEventListener(object, listener.getObject(), listener.getEvent());
187                }
188        }
189        
190        private void        addEventListener(Object                                                producer,
191                                             InjectObjectInformation        listener,
192                                             String                                                event)
193        {
194                //#### Bad location, no?
195                _linker.addEventListener(producer,
196                                         event,
197                                         getObject(listener),
198                                         listener.getLocation());
199        }
200        
201        private Object        getObject(InjectObjectInformation inject)
202        {
203                return _objectTranslator.translate(        inject.getModule(),
204                                                                                        inject.getType(),
205                                                                                        inject.getObject(),
206                                                                                        inject.getLocation());
207        }
208        
209        // Class to hold the key of a cached object (name + args)
210        static private class CachedObjectKey
211        {
212                public CachedObjectKey(String name, Object[] args)
213                {
214                        // CSOFF: MagicNumberCheck
215                        _name = name;
216                        _args = args;
217                        int hash = _name.hashCode() * 4321;
218                        for (int i = 0; i < _args.length; i++)
219                        {
220                                if (_args[i] != null)
221                                {
222                                        hash += _args[i].hashCode() * (567 + i);
223                                }
224                        }
225                        _hash = hash;
226                        // CSON: MagicNumberCheck
227                }
228                
229                public int        hashCode()
230                {
231                        return _hash;
232                }
233                
234                public boolean        equals(Object o)
235                {
236                        if (!(o instanceof CachedObjectKey))
237                        {
238                                return false;
239                        }
240                        CachedObjectKey that = (CachedObjectKey) o;
241                        if (!that._name.equals(this._name))
242                        {
243                                return false;
244                        }
245                        if (that._args.length != this._args.length)
246                        {
247                                return false;
248                        }
249                        for (int i = 0; i < _args.length; i++)
250                        {
251                                if (that._args[i] == this._args[i])
252                                {
253                                        continue;
254                                }
255                                if (        that._args[i] != null
256                                        &&        !that._args[i].equals(this._args[i]))
257                                {
258                                        return false;
259                                }
260                        }
261                        return true;
262                }
263                
264                private final String        _name;
265                private final Object[]        _args;
266                private final int                _hash;
267        }
268 
269        private final Log                                                                _logger;
270        private final EventLinker                                                _linker;
271        private final Map<String, ObjectContribution>        _config;
272        private final Map<CachedObjectKey, Object>                _cache;
273        private final Translator                                                _objectTranslator;
274        private final List<ObjectBuilderListener>                _listeners;
275}

[all classes][net.sourceforge.hiveutils.service.impl]
EMMA 2.0.5312 (C) Vladimir Roubtsov