]> git.argeo.org Git - lgpl/argeo-commons.git/blob - dao/AbstractMemoryDaoSupport.java
Prepare next development cycle
[lgpl/argeo-commons.git] / dao / AbstractMemoryDaoSupport.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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.argeo.server.dao;
18
19 import java.beans.PropertyEditor;
20 import java.io.InputStream;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.TreeMap;
27
28 import org.apache.commons.io.IOUtils;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.argeo.ArgeoException;
32 import org.springframework.beans.BeanWrapper;
33 import org.springframework.beans.BeanWrapperImpl;
34 import org.springframework.beans.BeansException;
35 import org.springframework.beans.factory.InitializingBean;
36 import org.springframework.context.ApplicationContext;
37 import org.springframework.context.ApplicationContextAware;
38 import org.springframework.core.io.Resource;
39
40 public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
41 ApplicationContextAware, InitializingBean {
42 private final static Log log = LogFactory
43 .getLog(AbstractMemoryDaoSupport.class);
44
45 private ClassLoader classLoader = getClass().getClassLoader();
46 private ApplicationContext applicationContext;
47 private List<Class<?>> additionalClasses = new ArrayList<Class<?>>();
48
49 private Map<Class<?>, Map<Object, Object>> model = new HashMap<Class<?>, Map<Object, Object>>();
50
51 private Map<String, Object> externalRefs = new HashMap<String, Object>();
52
53 private List<String> scannedPackages = new ArrayList<String>();
54
55 private List<Resource> resources = new ArrayList<Resource>();
56
57 private Map<Class<?>, PropertyEditor> customEditors = new HashMap<Class<?>, PropertyEditor>();;
58
59 protected abstract void load(InputStream in, List<Reference> references);
60
61 protected abstract Object findInternalRef(Reference reference);
62
63 public void afterPropertiesSet() throws Exception {
64 init();
65 }
66
67 public void init() {
68 for (PropertyEditor propertyEditor : customEditors.values())
69 if (propertyEditor instanceof LightDaoAware) {
70 ((LightDaoAware) propertyEditor).setLightDaoSupport(this);
71 }
72
73 // Load data
74 List<Reference> references = new ArrayList<Reference>();
75
76 for (Resource res : resources) {
77 InputStream in = null;
78 try {
79 in = res.getInputStream();
80 load(in, references);
81 } catch (Exception e) {
82 throw new ArgeoException("Cannot load stream", e);
83 } finally {
84 IOUtils.closeQuietly(in);
85 }
86 }
87
88 // Inject references
89 for (Reference ref : references) {
90 injectReference(ref);
91 }
92 if (log.isDebugEnabled())
93 log.debug(references.size() + " references linked");
94 }
95
96 public List<Class<?>> getSupportedClasses() {
97 List<Class<?>> res = new ArrayList<Class<?>>();
98 res.addAll(additionalClasses);
99 res.addAll(model.keySet());
100 return res;
101 }
102
103 protected void injectReference(Reference reference) {
104 BeanWrapper bw = new BeanWrapperImpl(reference.object);
105 Object targetObject;
106 if (reference.getExternalRef() != null) {
107 String ref = reference.getExternalRef();
108 if (externalRefs.containsKey(ref))
109 targetObject = externalRefs.get(ref);
110 else if (applicationContext != null)
111 targetObject = applicationContext.getBean(ref);
112 else {
113 targetObject = null;
114 log.warn("Ref " + ref + " not found");
115 }
116 } else {
117 targetObject = findInternalRef(reference);
118 }
119 bw.setPropertyValue(reference.property, targetObject);
120
121 }
122
123 protected BeanWrapper newBeanWrapper(Class<?> targetClass) {
124 BeanWrapperImpl bw = new BeanWrapperImpl(targetClass);
125 for (Class<?> clss : customEditors.keySet())
126 bw.registerCustomEditor(clss, customEditors.get(clss));
127 return bw;
128 }
129
130 @SuppressWarnings("unchecked")
131 public <T> T getByKey(Class<T> clss, Object key) {
132 if (key == null)
133 throw new ArgeoException("Key is null for " + clss);
134 return (T) model.get(findClass(clss)).get(key);
135 }
136
137 /**
138 * Slow.
139 *
140 * @return the first found
141 */
142 public <T> T getByField(Class<T> clss, String field, Object value) {
143 List<T> all = list(clss, null);
144 T res = null;
145 for (T obj : all) {
146 if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) {
147 res = obj;
148 break;
149 }
150 }
151 return res;
152 }
153
154 @SuppressWarnings("unchecked")
155 public <T> List<T> list(Class<T> clss, Object filter) {
156 List<T> res = new ArrayList<T>();
157
158 Class classToUse = findClass(clss);
159 if (classToUse != null)
160 res.addAll((Collection<T>) model.get(classToUse).values());
161
162 if (applicationContext != null)
163 res.addAll(applicationContext.getBeansOfType(clss).values());
164
165 return res;
166 }
167
168 @SuppressWarnings("unchecked")
169 protected Class findClass(Class parent) {
170 if (model.containsKey(parent))
171 return parent;
172
173 for (Class clss : model.keySet()) {
174 if (parent.isAssignableFrom(clss))
175 return clss;// return the first found
176 }
177 if (log.isDebugEnabled())
178 log.warn("No class found for " + parent.getName());
179 return null;
180 }
181
182 public void setApplicationContext(ApplicationContext applicationContext)
183 throws BeansException {
184 this.applicationContext = applicationContext;
185 }
186
187 /**
188 * When it should be stored under a different class (e.g. super class or
189 * interface)
190 */
191 public void saveOrUpdate(Object key, Object value, Class<?> clss) {
192 if (!model.containsKey(clss))
193 model.put(clss, new TreeMap<Object, Object>());
194 model.get(clss).put(key, value);
195 }
196
197 protected ClassLoader getClassLoader() {
198 return classLoader;
199 }
200
201 public void setExternalRefs(Map<String, Object> externalRefs) {
202 this.externalRefs = externalRefs;
203 }
204
205 public Map<String, Object> getExternalRefs() {
206 return externalRefs;
207 }
208
209 public void setScannedPackages(List<String> scannedPackages) {
210 this.scannedPackages = scannedPackages;
211 }
212
213 public List<String> getScannedPackages() {
214 return scannedPackages;
215 }
216
217 public void setResources(List<Resource> workbooks) {
218 this.resources = workbooks;
219 }
220
221 public List<Resource> getResources() {
222 return resources;
223 }
224
225 public void setClassLoader(ClassLoader classLoader) {
226 this.classLoader = classLoader;
227 }
228
229 public List<Class<?>> getAdditionalClasses() {
230 return additionalClasses;
231 }
232
233 public void setAdditionalClasses(List<Class<?>> additionalClasses) {
234 this.additionalClasses = additionalClasses;
235 }
236
237 public void setCustomEditors(Map<Class<?>, PropertyEditor> propertyEditors) {
238 this.customEditors = propertyEditors;
239 }
240
241 protected static class Reference {
242 private Object object;
243 private String property;
244 private String externalRef;
245
246 public Reference(Object object, String property, String externalRef) {
247 this.object = object;
248 this.property = property;
249 this.externalRef = externalRef;
250 }
251
252 public Object getObject() {
253 return object;
254 }
255
256 public String getProperty() {
257 return property;
258 }
259
260 public String getExternalRef() {
261 return externalRef;
262 }
263
264 }
265 }