Update light DAO
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 11 Nov 2009 12:36:25 +0000 (12:36 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 11 Nov 2009 12:36:25 +0000 (12:36 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@3083 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java
server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java
server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java [new file with mode: 0644]
server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java [new file with mode: 0644]
server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java
server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/CollectionsObject.java
server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/JxlDaoSupportTest.java
server/runtime/org.argeo.server.jxl/src/test/resources/dao/simple.xls

index 39655d4fe04812fc9a2027cab7c4fd1723b27294..9e0881bf0243e4a8479172f7dc6f134576f74cf2 100644 (file)
@@ -37,7 +37,7 @@ public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
 
        private List<String> scannedPackages = new ArrayList<String>();
 
-       private List<Resource> workbooks = new ArrayList<Resource>();
+       private List<Resource> resources = new ArrayList<Resource>();
 
        private Map<Class<?>, PropertyEditor> customEditors = new HashMap<Class<?>, PropertyEditor>();;
 
@@ -50,13 +50,15 @@ public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
        }
 
        public void init() {
-               // used to resolve inner references
-               // Map<String, List<Object>> tempRefs = new HashMap<String,
-               // List<Object>>();
+               for (PropertyEditor propertyEditor : customEditors.values())
+                       if (propertyEditor instanceof LightDaoAware) {
+                               ((LightDaoAware) propertyEditor).setLightDaoSupport(this);
+                       }
 
+               // Load data
                List<Reference> references = new ArrayList<Reference>();
 
-               for (Resource res : workbooks) {
+               for (Resource res : resources) {
                        InputStream in = null;
                        try {
                                in = res.getInputStream();
@@ -196,12 +198,12 @@ public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
                return scannedPackages;
        }
 
-       public void setWorkbooks(List<Resource> workbooks) {
-               this.workbooks = workbooks;
+       public void setResources(List<Resource> workbooks) {
+               this.resources = workbooks;
        }
 
-       public List<Resource> getWorkbooks() {
-               return workbooks;
+       public List<Resource> getResources() {
+               return resources;
        }
 
        public void setClassLoader(ClassLoader classLoader) {
index a2195b4d46a1bff5ba67017b09aa96f7da6190cf..f81135753efe35dd164ad36c1dd76a050db46e22 100644 (file)
@@ -5,8 +5,15 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.server.ArgeoServerException;
+
 public abstract class AbstractTabularDaoSupport extends
                AbstractMemoryDaoSupport {
+       private final static Log log = LogFactory
+                       .getLog(AbstractTabularDaoSupport.class);
+       
        private Map<String, List<Object>> tabularView = new HashMap<String, List<Object>>();
 
        @Override
@@ -26,6 +33,35 @@ public abstract class AbstractTabularDaoSupport extends
                tabularView.get(tableName).add(object);
        }
 
+       protected Class<?> findClassToInstantiate(String tableName) {
+               // TODO: ability to map sheet names and class names
+               String className = tableName;
+               Class<?> clss = null;
+               try {
+                       clss = getClassLoader().loadClass(className);
+                       return clss;
+               } catch (ClassNotFoundException e) {
+                       // silent
+               }
+
+               scannedPkgs: for (String pkg : getScannedPackages()) {
+                       try {
+                               clss = getClassLoader().loadClass(pkg.trim() + "." + className);
+                               break scannedPkgs;
+                       } catch (ClassNotFoundException e) {
+                               // silent
+                               if (log.isTraceEnabled())
+                                       log.trace(e.getMessage());
+                       }
+               }
+
+               if (clss == null)
+                       throw new ArgeoServerException("Cannot find a class for table "
+                                       + tableName);
+
+               return clss;
+       }
+
        protected static class TabularInternalReference extends Reference {
                private String targetTableName;
                private Integer targetRow;
diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java
new file mode 100644 (file)
index 0000000..049299b
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.server.dao;
+
+public interface LightDaoAware {
+       public void setLightDaoSupport(LightDaoSupport lightDaoSupport);
+}
diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java
new file mode 100644 (file)
index 0000000..3633ce4
--- /dev/null
@@ -0,0 +1,44 @@
+package org.argeo.server.dao;
+
+import java.beans.PropertyEditorSupport;
+
+import org.argeo.server.ArgeoServerException;
+
+public class LightDaoPropertyEditor extends PropertyEditorSupport implements
+               LightDaoAware {
+       private LightDaoSupport lightDaoSupport;
+
+       private Class<?> targetClass;
+       /** Can be null */
+       private String businessIdField;
+
+       @Override
+       public String getAsText() {
+               return getValue().toString();
+       }
+
+       @Override
+       public void setAsText(String text) throws IllegalArgumentException {
+               if (targetClass == null)
+                       throw new ArgeoServerException("Target class cannot be null");
+
+               if (businessIdField != null)
+                       setValue(lightDaoSupport.getByField(targetClass, businessIdField,
+                                       text));
+               else
+                       setValue(lightDaoSupport.getByKey(targetClass, text));
+       }
+
+       public void setLightDaoSupport(LightDaoSupport lightDaoSupport) {
+               this.lightDaoSupport = lightDaoSupport;
+       }
+
+       public void setTargetClass(Class<?> targetClass) {
+               this.targetClass = targetClass;
+       }
+
+       public void setBusinessIdField(String businessIdField) {
+               this.businessIdField = businessIdField;
+       }
+
+}
index 2e31dbddd6e5f635c07c0e32f0f3a3185e72bdc0..79fa2a606efb0d699b9cc0f4a5d46dd11ad43218 100644 (file)
@@ -1,10 +1,12 @@
 package org.argeo.server.jxl.dao;
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 import jxl.Cell;
 import jxl.CellType;
@@ -24,6 +26,7 @@ import org.argeo.server.dao.LightDaoSupport;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.io.Resource;
 import org.springframework.util.StringUtils;
 
 public class JxlDaoSupport extends AbstractTabularDaoSupport implements
@@ -50,23 +53,52 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
 
        protected void loadSheet(Sheet sheet, List<Reference> references)
                        throws JXLException {
+               String sheetName = sheet.getName();
                if (log.isTraceEnabled())
-                       log.debug("Instantiate sheet " + sheet.getName());
+                       log.debug("Instantiate sheet " + sheetName);
 
-               Cell[] firstRow = sheet.getRow(0);
-
-               Class<?> clss = findClassToInstantiate(sheet);
-               // model.put(clss, new TreeMap<Object, Object>());
+               String tableName;
+               int hashIndex = sheetName.lastIndexOf('#');
+               if (hashIndex >= 0) {
+                       tableName = sheetName.substring(0, hashIndex);
+               } else {
+                       tableName = sheetName;
+               }
 
-               // tempRefs.put(sheet.getName(), new ArrayList<Object>());
+               Class<?> clss = findClassToInstantiate(tableName);
 
-               String keyProperty = firstRow[0].getContents();
+               if (hashIndex >= 0) {
+                       // see
+                       // http://stackoverflow.com/questions/451452/valid-characters-for-excel-sheet-names
+                       BeanWrapper bw = newBeanWrapper(clss);
+                       StringTokenizer espSt = new StringTokenizer(sheetName
+                                       .substring(hashIndex + 1), "&=");
+                       String keyProperty = null;
+                       while (espSt.hasMoreTokens()) {
+                               String fieldName = espSt.nextToken();
+                               if (keyProperty == null)
+                                       keyProperty = fieldName;
+                               if (!espSt.hasMoreTokens())
+                                       throw new ArgeoServerException("Badly formatted sheetname "
+                                                       + sheetName);
+                               String fieldValue = espSt.nextToken();
+                               bw.setPropertyValue(fieldName, fieldValue);
+                               loadAsObject(bw, sheet, references);
+                               saveOrUpdate(bw.getPropertyValue(keyProperty), bw
+                                               .getWrappedInstance(), clss);
+                       }
 
-               if (keyProperty.charAt(keyProperty.length() - 1) == '>') {
-                       loadAsColumns(clss, keyProperty.substring(0,
-                                       keyProperty.length() - 1), sheet, firstRow, references);
                } else {
-                       loadAsRows(clss, keyProperty, sheet, firstRow, references);
+
+                       Cell[] firstRow = sheet.getRow(0);
+                       String keyProperty = firstRow[0].getContents();
+
+                       if (keyProperty.charAt(keyProperty.length() - 1) == '>') {
+                               loadAsColumns(clss, keyProperty.substring(0, keyProperty
+                                               .length() - 1), sheet, firstRow, references);
+                       } else {
+                               loadAsRows(clss, keyProperty, sheet, firstRow, references);
+                       }
                }
        }
 
@@ -128,13 +160,11 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                                        String firstColContents = firstColumn[row].getContents();
                                        mapRows: for (; row < column.length; row++) {
                                                cell = column[row];
-
                                                Object key = firstColContents;
-                                               CellType type = cell.getType();
                                                if (log.isTraceEnabled())
                                                        log.trace("   row=" + row + ", firstColContents="
                                                                        + firstColContents + ", key=" + key
-                                                                       + ", type=" + type);
+                                                                       + ", type=" + cell.getType());
                                                Object cellValue = getCellValue(cell);
                                                map.put(key, cellValue);
 
@@ -165,6 +195,72 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                }// columns
        }
 
+       protected void loadAsObject(BeanWrapper bw, Sheet sheet,
+                       List<Reference> references) {
+               Cell[] firstColumn = sheet.getColumn(0);
+               for (int row = 0; row < firstColumn.length; row++) {
+                       if (log.isTraceEnabled())
+                               log.trace(" row " + row);
+                       Cell[] currentRow = sheet.getRow(row);
+                       String propertyName = firstColumn[row].getContents();
+                       Class<?> rowType = bw.getPropertyType(propertyName);
+                       if (Map.class.isAssignableFrom(rowType)) {
+                               Map<Object, Object> map = new HashMap<Object, Object>();
+                               if (currentRow.length == 1
+                                               || currentRow[1].getContents().trim().equals("")) {
+                                       // simple map
+                               } else {
+                                       // map of maps
+                                       List<Object> subKeys = new ArrayList<Object>();
+                                       for (int col = 1; col < currentRow.length; col++) {
+                                               subKeys.add(getCellValue(currentRow[col]));
+                                       }
+                                       row++;
+                                       String firstColContents = firstColumn[row].getContents();
+                                       mapRows: for (; row < firstColumn.length; row++) {
+                                               currentRow = sheet.getRow(row);
+
+                                               Object key = firstColContents;
+                                               Map<Object, Object> subMap = new HashMap<Object, Object>();
+
+                                               for (int col = 0; col < currentRow.length
+                                                               && col < subKeys.size(); col++) {
+                                                       Object subKey = subKeys.get(col);
+                                                       Cell cell = currentRow[col];
+                                                       if (log.isTraceEnabled())
+                                                               log.trace("   row=" + row
+                                                                               + ", firstColContents="
+                                                                               + firstColContents + ", subKey="
+                                                                               + subKey + ", type=" + cell.getType());
+                                                       Object cellValue = getCellValue(cell);
+                                                       subMap.put(subKey, cellValue);
+                                               }
+                                               map.put(key, subMap);
+
+                                               // check next row too see if one should break
+                                               if (row < firstColumn.length - 1)
+                                                       firstColContents = firstColumn[row + 1]
+                                                                       .getContents();
+                                               if (bw.isWritableProperty(firstColContents)
+                                                               || firstColContents.trim().equals("")
+                                                               || row == firstColumn.length - 1) {
+                                                       bw.setPropertyValue(propertyName, map);
+                                                       if (log.isTraceEnabled())
+                                                               log.trace(" set map " + propertyName
+                                                                               + " of size " + map.size());
+                                                       break mapRows;// map is over
+                                               }
+                                       }
+
+                               }
+                       } else if (List.class.isAssignableFrom(rowType)) {
+                               throw new UnsupportedOperationException();
+                       } else {
+                               bw.setPropertyValue(propertyName, getCellValue(currentRow[1]));
+                       }
+               }
+       }
+
        protected void loadCell(Cell cell, BeanWrapper bw, String propertyName,
                        String keyProperty, Integer row, List<Reference> references)
                        throws JXLException {
@@ -244,35 +340,6 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                throw new UnsupportedOperationException();
        }
 
-       protected Class<?> findClassToInstantiate(Sheet sheet) {
-               // TODO: ability to map sheet names and class names
-               String className = sheet.getName();
-               Class<?> clss = null;
-               try {
-                       clss = getClassLoader().loadClass(className);
-                       return clss;
-               } catch (ClassNotFoundException e) {
-                       // silent
-               }
-
-               scannedPkgs: for (String pkg : getScannedPackages()) {
-                       try {
-                               clss = getClassLoader().loadClass(pkg.trim() + "." + className);
-                               break scannedPkgs;
-                       } catch (ClassNotFoundException e) {
-                               // silent
-                               if (log.isTraceEnabled())
-                                       log.trace(e.getMessage());
-                       }
-               }
-
-               if (clss == null)
-                       throw new ArgeoServerException("Cannot find a class for sheet "
-                                       + sheet.getName());
-
-               return clss;
-       }
-
        public void setEncoding(String encoding) {
                this.encoding = encoding;
        }
@@ -281,4 +348,11 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                this.locale = locale;
        }
 
+       /** @deprecated use {@link #setResources(List)} instead. */
+       public void setWorkbooks(List<Resource> workbooks) {
+               setResources(workbooks);
+               log.warn("###\n" + "### Use of the 'workbooks' property is deprecated!"
+                               + " It will be removed in one of the next releases."
+                               + " Use the 'resources' property instead." + "\n###");
+       }
 }
index 2e5f33b2865b7a1a21729787d694f4a732eade01..d2fe3a3b1d0bab0f97523e1468ea9fcff0d3c4ae 100644 (file)
@@ -12,6 +12,7 @@ public class CollectionsObject {
        private List<String> stringList = new ArrayList<String>();
        private Map<String, Float> floatMap = new HashMap<String, Float>();
        private Map<SimpleObject, String> objectMap = new HashMap<SimpleObject, String>();
+       private Map<String, Map<String, String>> mapOfMaps = new HashMap<String, Map<String, String>>();
 
        public String getId() {
                return id;
@@ -60,4 +61,12 @@ public class CollectionsObject {
        public void setObjectMap(Map<SimpleObject, String> objectMap) {
                this.objectMap = objectMap;
        }
+
+       public Map<String, Map<String, String>> getMapOfMaps() {
+               return mapOfMaps;
+       }
+
+       public void setMapOfMaps(Map<String, Map<String, String>> mapOfMaps) {
+               this.mapOfMaps = mapOfMaps;
+       }
 }
index 51b209656c9a66d4ff3685e2342d1d5d2c72310b..4047459915bcc15ddb765267fd443d804d1335cf 100644 (file)
@@ -11,7 +11,7 @@ public class JxlDaoSupportTest extends TestCase {
                JxlDaoSupport jsd = new JxlDaoSupport();
                jsd.getExternalRefs().put("test", new OtherObject());
 
-               jsd.getWorkbooks().add(new ClassPathResource("/dao/simple.xls"));
+               jsd.getResources().add(new ClassPathResource("/dao/simple.xls"));
                jsd.init();
 
                SimpleObject soAaa = jsd.getByKey(SimpleObject.class, "aaa");
@@ -32,6 +32,6 @@ public class JxlDaoSupportTest extends TestCase {
 
                List<CollectionsObject> collectionsObjects = jsd.list(
                                CollectionsObject.class, null);
-               assertEquals(3, collectionsObjects.size());
+               assertEquals(4, collectionsObjects.size());
        }
 }
index f04b9d87788c0cea0dc2ecea49ba2f431764ca34..6cb4c2ee49a210b5e1f524e7abcc8bc17c37a68a 100644 (file)
Binary files a/server/runtime/org.argeo.server.jxl/src/test/resources/dao/simple.xls and b/server/runtime/org.argeo.server.jxl/src/test/resources/dao/simple.xls differ