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