Try to deal with encoding
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jxl / src / main / java / org / argeo / server / jxl / dao / JxlDaoSupport.java
index ef3dcf04b3de3532958278c69ee4befaf0a601d3..fecd7f2911bfd0b1bd0439d021536110bf874b0a 100644 (file)
@@ -6,31 +6,40 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 import jxl.Cell;
+import jxl.CellType;
 import jxl.FormulaCell;
 import jxl.JXLException;
+import jxl.LabelCell;
+import jxl.NumberCell;
 import jxl.Sheet;
 import jxl.Workbook;
+import jxl.WorkbookSettings;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.server.ArgeoServerException;
+import org.argeo.server.dao.LightDaoSupport;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.BeanWrapperImpl;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.generic.GenericBeanFactoryAccessor;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.core.io.Resource;
 import org.springframework.util.StringUtils;
 
-public class JxlDaoSupport implements ApplicationContextAware, InitializingBean {
+public class JxlDaoSupport implements LightDaoSupport, ApplicationContextAware,
+               InitializingBean {
        private final static Log log = LogFactory.getLog(JxlDaoSupport.class);
 
        private ClassLoader classLoader = getClass().getClassLoader();
        private ApplicationContext applicationContext;
+       private List<Class<?>> additionalClasses = new ArrayList<Class<?>>();
 
        private Map<Class<?>, Map<Object, Object>> model = new HashMap<Class<?>, Map<Object, Object>>();
 
@@ -40,38 +49,54 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
 
        private List<Resource> workbooks = new ArrayList<Resource>();
 
+       private Integer charset = 0;
+
        public void afterPropertiesSet() throws Exception {
+               init();
+       }
+
+       public void init() {
+               // used to resolve inner references
+               Map<String, List<Object>> tempRefs = new HashMap<String, List<Object>>();
+
+               List<Reference> references = new ArrayList<Reference>();
+
                for (Resource res : workbooks) {
                        InputStream in = null;
                        try {
                                in = res.getInputStream();
-                               load(in);
+                               load(in, references, tempRefs);
+                       } catch (Exception e) {
+                               throw new ArgeoServerException("Cannot load stream", e);
                        } finally {
                                IOUtils.closeQuietly(in);
                        }
                }
 
+               // Inject references
+               for (Reference ref : references) {
+                       injectReference(ref, tempRefs);
+               }
+               if (log.isDebugEnabled())
+                       log.debug(references.size() + " references linked");
        }
 
-       public void load(InputStream in) {
-               try {
-                       // used to resolve inner references
-                       Map<String, List<Object>> tempRefs = new HashMap<String, List<Object>>();
-
-                       List<Reference> references = new ArrayList<Reference>();
-
-                       Workbook workbook = Workbook.getWorkbook(in);
+       public List<Class<?>> getSupportedClasses() {
+               List<Class<?>> res = new ArrayList<Class<?>>();
+               res.addAll(additionalClasses);
+               res.addAll(model.keySet());
+               return res;
+       }
 
+       public void load(InputStream in, List<Reference> references,
+                       Map<String, List<Object>> tempRefs) {
+               try {
+                       WorkbookSettings workbookSettings = new WorkbookSettings();
+                       workbookSettings.setCharacterSet(charset);
+                       Workbook workbook = Workbook.getWorkbook(in, workbookSettings);
                        for (Sheet sheet : workbook.getSheets()) {
                                loadSheet(sheet, references, tempRefs);
                        }
-
-                       for (Reference ref : references) {
-                               injectReference(ref, tempRefs);
-                       }
-                       if (log.isDebugEnabled())
-                               log.debug(references.size() + " references linked");
-
                } catch (Exception e) {
                        throw new ArgeoServerException("Cannot load workbook", e);
                }
@@ -85,7 +110,7 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                Cell[] firstRow = sheet.getRow(0);
 
                Class<?> clss = findClassToInstantiate(sheet);
-               model.put(clss, new HashMap<Object, Object>());
+               model.put(clss, new TreeMap<Object, Object>());
 
                tempRefs.put(sheet.getName(), new ArrayList<Object>());
 
@@ -126,6 +151,10 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                if (cell instanceof FormulaCell) {
                        String formula = ((FormulaCell) cell).getFormula();
                        int index = formula.indexOf('!');
+                       if (index < 0)
+                               throw new ArgeoServerException("Cannot interpret formula "
+                                               + formula);
+                       ;
                        String targetSheet = formula.substring(0, index);
                        // assume no double letters!!
                        String targetRowStr = formula.substring(index + 2);
@@ -141,6 +170,17 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                                                + ", targetRow=" + targetRow);
                } else {
                        String contents = cell.getContents();
+
+//                     if (cell.getType() == CellType.LABEL) {
+//                             LabelCell lc = (LabelCell) cell;
+//                             contents = lc.getString();
+//                     } else if (cell.getType() == CellType.NUMBER) {
+//                             NumberCell nc = (NumberCell) cell;
+//                             contents = new Double(nc.getValue()).toString();
+//                     } else {
+//                             contents = cell.getContents();
+//                     }
+
                        if (propertyName.equals(keyProperty)
                                        && !StringUtils.hasText(contents)) {
                                // auto allocate key column if empty
@@ -223,10 +263,36 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                return (T) model.get(findClass(clss)).get(key);
        }
 
+       /**
+        * Slow.
+        * 
+        * @return the first found
+        */
+       public <T> T getByField(Class<T> clss, String field, Object value) {
+               List<T> 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")
        public <T> List<T> list(Class<T> clss, Object filter) {
-               return new ArrayList<T>((Collection<T>) model.get(findClass(clss))
-                               .values());
+               List<T> res = new ArrayList<T>();
+
+               Class classToUse = findClass(clss);
+               if (classToUse != null)
+                       res.addAll((Collection<T>) model.get(classToUse).values());
+
+               if (applicationContext != null)
+                       res.addAll(new GenericBeanFactoryAccessor(applicationContext)
+                                       .getBeansOfType(clss).values());
+
+               return res;
        }
 
        @SuppressWarnings("unchecked")
@@ -238,8 +304,7 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                        if (parent.isAssignableFrom(clss))
                                return clss;// return the first found
                }
-               throw new ArgeoServerException("No implementing class found for "
-                               + parent);
+               return null;
        }
 
        public void setApplicationContext(ApplicationContext applicationContext)
@@ -275,6 +340,18 @@ public class JxlDaoSupport implements ApplicationContextAware, InitializingBean
                this.classLoader = classLoader;
        }
 
+       public List<Class<?>> getAdditionalClasses() {
+               return additionalClasses;
+       }
+
+       public void setAdditionalClasses(List<Class<?>> additionalClasses) {
+               this.additionalClasses = additionalClasses;
+       }
+
+       public void setCharset(Integer charset) {
+               this.charset = charset;
+       }
+
        public static class Reference {
                private Object object;
                private String property;