Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
MapperFactory |
|
| 1.3333333333333333;1.333 |
1 | /* | |
2 | * Copyright 2003-2004 The Apache Software Foundation. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | package org.apache.commons.mapper; | |
18 | ||
19 | import java.util.ArrayList; | |
20 | import java.util.HashMap; | |
21 | import java.util.Iterator; | |
22 | import java.util.List; | |
23 | import java.util.Map; | |
24 | ||
25 | import org.apache.commons.mapper.util.ObjectFactory; | |
26 | ||
27 | /** | |
28 | * <code>MapperFactory</code> is responsible for creating mappers based on | |
29 | * domain class names or any other String name. This allows a domain class to | |
30 | * be a value bean and delegate data storage responsibility to a specific | |
31 | * <code>Mapper</code> subclass. | |
32 | * <p> | |
33 | * <code>MapperFactory.getMapper()</code> method uses caching to prevent | |
34 | * creating mappers multiple times. This means that a Mapper returned from | |
35 | * <code>getMapper()</code> will not be a new instance which could cause | |
36 | * problems in a multi-threaded environment (the servlet container environment | |
37 | * is multi-threaded). Mappers returned by the <code>MapperFactory</code> | |
38 | * should not use instance variables to maintain state, rather, they should | |
39 | * use local method variables so they are thread-safe. | |
40 | * <p> | |
41 | * Note that you do not need to subclass <code>MapperFactory</code> to specify | |
42 | * the specific <code>Mapper</code> implementation classes to return from | |
43 | * <code>getMapper()</code>. Because <code>Mapper</code> implementation | |
44 | * classes are defined in a <code>Map</code>, you can have any combination of | |
45 | * <code>Mapper</code> types in use at the same time. For example, you could | |
46 | * have EjbPersonMapper using an EJB to persist Person objects and a | |
47 | * JdbcOrderMapper using JDBC calls to persist Order objects. You can register | |
48 | * <code>MapperFactoryListener</code> implementations with the factory to | |
49 | * initialize the various types of Mappers when they are created. | |
50 | * | |
51 | * @see Mapper | |
52 | * @see MapperFactoryListener | |
53 | */ | |
54 | public class MapperFactory { | |
55 | ||
56 | /** | |
57 | * This factory actually creates the mappers. | |
58 | */ | |
59 | 0 | protected ObjectFactory factory = null; |
60 | ||
61 | /** | |
62 | * Holds mapper instances that have already been created. The key is a | |
63 | * String name which is often a domain class' name and the value is a | |
64 | * <code>Mapper</code> instance. | |
65 | */ | |
66 | 0 | private Map mapperCache = new HashMap(); |
67 | ||
68 | /** | |
69 | * The List of listeners to notify when a Mapper is created. | |
70 | */ | |
71 | 0 | private List listeners = new ArrayList(); |
72 | ||
73 | /** | |
74 | * Create a new MapperFactory with the mappings contained in the given Map. | |
75 | * @param map Any map containing logical names (often domain class names) | |
76 | * as the keys and mapper class names as the values. | |
77 | * @throws IllegalArgumentException if there is a problem finding the | |
78 | * mapped classes. | |
79 | */ | |
80 | public MapperFactory(Map map) { | |
81 | 0 | super(); |
82 | 0 | this.factory = new ObjectFactory(map); |
83 | 0 | } |
84 | ||
85 | /** | |
86 | * Factory method for getting the mapper associated with the given class. | |
87 | * @param mappedClass The class whose mapper should be returned | |
88 | * @return Mapper the mapper associated with the given class | |
89 | * @throws IllegalArgumentException if the given Class was not found in | |
90 | * the map or there was an error creating an instance of the Mapper. This | |
91 | * is usually caused by a missing public no-arg constructor. | |
92 | */ | |
93 | public Mapper getMapper(Class mappedClass) { | |
94 | 0 | return this.getMapper(mappedClass.getName()); |
95 | } | |
96 | ||
97 | /** | |
98 | * Factory method for getting the mapper associated with the given class. | |
99 | * @param name The name of the mapper to be returned. | |
100 | * @return Mapper the mapper associated with the given name. | |
101 | * @throws IllegalArgumentException if the given name was not found in | |
102 | * the map or there was an error creating an instance of the Mapper. This | |
103 | * is usually caused by a missing public no-arg constructor. | |
104 | */ | |
105 | public Mapper getMapper(String name) { | |
106 | ||
107 | 0 | synchronized (this.mapperCache) { |
108 | 0 | Mapper m = (Mapper) this.mapperCache.get(name); |
109 | 0 | if (m == null) { |
110 | 0 | m = (Mapper) this.factory.create(name); |
111 | 0 | this.fireMapperCreated(m); |
112 | 0 | this.mapperCache.put(name, m); |
113 | } | |
114 | ||
115 | 0 | return m; |
116 | 0 | } |
117 | } | |
118 | ||
119 | /** | |
120 | * Register a listener with this MapperFactory to receive notifications | |
121 | * of events. | |
122 | * @param listener | |
123 | */ | |
124 | public void addMapperFactoryListener(MapperFactoryListener listener) { | |
125 | 0 | synchronized (this.listeners) { |
126 | 0 | this.listeners.add(listener); |
127 | 0 | } |
128 | 0 | } |
129 | ||
130 | /** | |
131 | * Unregister a listener from this MapperFactory. | |
132 | * @param listener | |
133 | */ | |
134 | public void removeMapperFactoryListener(MapperFactoryListener listener) { | |
135 | 0 | synchronized (this.listeners) { |
136 | 0 | this.listeners.remove(listener); |
137 | 0 | } |
138 | 0 | } |
139 | ||
140 | /** | |
141 | * Call the mapperCreated() method of all registered listeners. | |
142 | * @param created The Mapper that was just created and should be passed to | |
143 | * the listeners for initialization. | |
144 | */ | |
145 | private void fireMapperCreated(Mapper created) { | |
146 | 0 | MapperFactoryEvent event = new MapperFactoryEvent(this, created); |
147 | ||
148 | 0 | synchronized (this.listeners) { |
149 | 0 | Iterator iter = this.listeners.iterator(); |
150 | 0 | while (iter.hasNext()) { |
151 | 0 | MapperFactoryListener listener = (MapperFactoryListener) iter.next(); |
152 | 0 | listener.mapperCreated(event); |
153 | 0 | } |
154 | 0 | } |
155 | ||
156 | 0 | } |
157 | ||
158 | } |