X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.server.core%2Fsrc%2Forg%2Fargeo%2Fserver%2Fdao%2FAbstractMemoryDaoSupport.java;fp=org.argeo.server.core%2Fsrc%2Forg%2Fargeo%2Fserver%2Fdao%2FAbstractMemoryDaoSupport.java;h=f9af51bcf9a179c00c90d63f003e97b57a260fb1;hb=79bc665d4b1eeccb7416279750bc60a138c81988;hp=0000000000000000000000000000000000000000;hpb=f00611ca313420ab96d44889577b46f31c2dcb35;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java new file mode 100644 index 000000000..f9af51bcf --- /dev/null +++ b/org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.server.dao; + +import java.beans.PropertyEditor; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.io.Resource; + +public abstract class AbstractMemoryDaoSupport implements LightDaoSupport, + ApplicationContextAware, InitializingBean { + private final static Log log = LogFactory + .getLog(AbstractMemoryDaoSupport.class); + + private ClassLoader classLoader = getClass().getClassLoader(); + private ApplicationContext applicationContext; + private List> additionalClasses = new ArrayList>(); + + private Map, Map> model = new HashMap, Map>(); + + private Map externalRefs = new HashMap(); + + private List scannedPackages = new ArrayList(); + + private List resources = new ArrayList(); + + private Map, PropertyEditor> customEditors = new HashMap, PropertyEditor>();; + + protected abstract void load(InputStream in, List references); + + protected abstract Object findInternalRef(Reference reference); + + public void afterPropertiesSet() throws Exception { + init(); + } + + public void init() { + for (PropertyEditor propertyEditor : customEditors.values()) + if (propertyEditor instanceof LightDaoAware) { + ((LightDaoAware) propertyEditor).setLightDaoSupport(this); + } + + // Load data + List references = new ArrayList(); + + for (Resource res : resources) { + InputStream in = null; + try { + in = res.getInputStream(); + load(in, references); + } catch (Exception e) { + throw new ArgeoException("Cannot load stream", e); + } finally { + IOUtils.closeQuietly(in); + } + } + + // Inject references + for (Reference ref : references) { + injectReference(ref); + } + if (log.isDebugEnabled()) + log.debug(references.size() + " references linked"); + } + + public List> getSupportedClasses() { + List> res = new ArrayList>(); + res.addAll(additionalClasses); + res.addAll(model.keySet()); + return res; + } + + protected void injectReference(Reference reference) { + BeanWrapper bw = new BeanWrapperImpl(reference.object); + Object targetObject; + if (reference.getExternalRef() != null) { + String ref = reference.getExternalRef(); + if (externalRefs.containsKey(ref)) + targetObject = externalRefs.get(ref); + else if (applicationContext != null) + targetObject = applicationContext.getBean(ref); + else { + targetObject = null; + log.warn("Ref " + ref + " not found"); + } + } else { + targetObject = findInternalRef(reference); + } + bw.setPropertyValue(reference.property, targetObject); + + } + + protected BeanWrapper newBeanWrapper(Class targetClass) { + BeanWrapperImpl bw = new BeanWrapperImpl(targetClass); + for (Class clss : customEditors.keySet()) + bw.registerCustomEditor(clss, customEditors.get(clss)); + return bw; + } + + @SuppressWarnings("unchecked") + public T getByKey(Class clss, Object key) { + if (key == null) + throw new ArgeoException("Key is null for " + clss); + return (T) model.get(findClass(clss)).get(key); + } + + /** + * Slow. + * + * @return the first found + */ + public T getByField(Class clss, String field, Object value) { + List all = list(clss, null); + T res = null; + for (T obj : all) { + if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) { + res = obj; + break; + } + } + return res; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public List list(Class clss, Object filter) { + List res = new ArrayList(); + + Class classToUse = findClass(clss); + if (classToUse != null) + res.addAll((Collection) model.get(classToUse).values()); + + if (applicationContext != null) + res.addAll(applicationContext.getBeansOfType(clss).values()); + + return res; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Class findClass(Class parent) { + if (model.containsKey(parent)) + return parent; + + for (Class clss : model.keySet()) { + if (parent.isAssignableFrom(clss)) + return clss;// return the first found + } + if (log.isDebugEnabled()) + log.warn("No class found for " + parent.getName()); + return null; + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + /** + * When it should be stored under a different class (e.g. super class or + * interface) + */ + public void saveOrUpdate(Object key, Object value, Class clss) { + if (!model.containsKey(clss)) + model.put(clss, new TreeMap()); + model.get(clss).put(key, value); + } + + protected ClassLoader getClassLoader() { + return classLoader; + } + + public void setExternalRefs(Map externalRefs) { + this.externalRefs = externalRefs; + } + + public Map getExternalRefs() { + return externalRefs; + } + + public void setScannedPackages(List scannedPackages) { + this.scannedPackages = scannedPackages; + } + + public List getScannedPackages() { + return scannedPackages; + } + + public void setResources(List workbooks) { + this.resources = workbooks; + } + + public List getResources() { + return resources; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public List> getAdditionalClasses() { + return additionalClasses; + } + + public void setAdditionalClasses(List> additionalClasses) { + this.additionalClasses = additionalClasses; + } + + public void setCustomEditors(Map, PropertyEditor> propertyEditors) { + this.customEditors = propertyEditors; + } + + protected static class Reference { + private Object object; + private String property; + private String externalRef; + + public Reference(Object object, String property, String externalRef) { + this.object = object; + this.property = property; + this.externalRef = externalRef; + } + + public Object getObject() { + return object; + } + + public String getProperty() { + return property; + } + + public String getExternalRef() { + return externalRef; + } + + } +}