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