From f99d677ed0ff66bf89b2662439802a240ee2e884 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 11 Nov 2009 12:36:25 +0000 Subject: [PATCH] Update light DAO git-svn-id: https://svn.argeo.org/commons/trunk@3083 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../server/dao/AbstractMemoryDaoSupport.java | 20 ++- .../server/dao/AbstractTabularDaoSupport.java | 36 ++++ .../org/argeo/server/dao/LightDaoAware.java | 5 + .../server/dao/LightDaoPropertyEditor.java | 44 +++++ .../argeo/server/jxl/dao/JxlDaoSupport.java | 160 +++++++++++++----- .../server/jxl/dao/CollectionsObject.java | 9 + .../server/jxl/dao/JxlDaoSupportTest.java | 4 +- .../src/test/resources/dao/simple.xls | Bin 9216 -> 10752 bytes 8 files changed, 224 insertions(+), 54 deletions(-) create mode 100644 server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java create mode 100644 server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java index 39655d4fe..9e0881bf0 100644 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java @@ -37,7 +37,7 @@ public abstract class AbstractMemoryDaoSupport implements LightDaoSupport, private List scannedPackages = new ArrayList(); - private List workbooks = new ArrayList(); + private List resources = new ArrayList(); private Map, PropertyEditor> customEditors = new HashMap, PropertyEditor>();; @@ -50,13 +50,15 @@ public abstract class AbstractMemoryDaoSupport implements LightDaoSupport, } public void init() { - // used to resolve inner references - // Map> tempRefs = new HashMap>(); + for (PropertyEditor propertyEditor : customEditors.values()) + if (propertyEditor instanceof LightDaoAware) { + ((LightDaoAware) propertyEditor).setLightDaoSupport(this); + } + // Load data List references = new ArrayList(); - 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 workbooks) { - this.workbooks = workbooks; + public void setResources(List workbooks) { + this.resources = workbooks; } - public List getWorkbooks() { - return workbooks; + public List getResources() { + return resources; } public void setClassLoader(ClassLoader classLoader) { diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java index a2195b4d4..f81135753 100644 --- a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java @@ -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> tabularView = new HashMap>(); @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 index 000000000..049299bec --- /dev/null +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java @@ -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 index 000000000..3633ce430 --- /dev/null +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java @@ -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; + } + +} diff --git a/server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java b/server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java index 2e31dbddd..79fa2a606 100644 --- a/server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java +++ b/server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java @@ -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 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()); + String tableName; + int hashIndex = sheetName.lastIndexOf('#'); + if (hashIndex >= 0) { + tableName = sheetName.substring(0, hashIndex); + } else { + tableName = sheetName; + } - // tempRefs.put(sheet.getName(), new ArrayList()); + 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 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 map = new HashMap(); + if (currentRow.length == 1 + || currentRow[1].getContents().trim().equals("")) { + // simple map + } else { + // map of maps + List subKeys = new ArrayList(); + 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 subMap = new HashMap(); + + 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 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 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###"); + } } diff --git a/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/CollectionsObject.java b/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/CollectionsObject.java index 2e5f33b28..d2fe3a3b1 100644 --- a/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/CollectionsObject.java +++ b/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/CollectionsObject.java @@ -12,6 +12,7 @@ public class CollectionsObject { private List stringList = new ArrayList(); private Map floatMap = new HashMap(); private Map objectMap = new HashMap(); + private Map> mapOfMaps = new HashMap>(); public String getId() { return id; @@ -60,4 +61,12 @@ public class CollectionsObject { public void setObjectMap(Map objectMap) { this.objectMap = objectMap; } + + public Map> getMapOfMaps() { + return mapOfMaps; + } + + public void setMapOfMaps(Map> mapOfMaps) { + this.mapOfMaps = mapOfMaps; + } } diff --git a/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/JxlDaoSupportTest.java b/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/JxlDaoSupportTest.java index 51b209656..404745991 100644 --- a/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/JxlDaoSupportTest.java +++ b/server/runtime/org.argeo.server.jxl/src/test/java/org/argeo/server/jxl/dao/JxlDaoSupportTest.java @@ -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 collectionsObjects = jsd.list( CollectionsObject.class, null); - assertEquals(3, collectionsObjects.size()); + assertEquals(4, collectionsObjects.size()); } } diff --git a/server/runtime/org.argeo.server.jxl/src/test/resources/dao/simple.xls b/server/runtime/org.argeo.server.jxl/src/test/resources/dao/simple.xls index f04b9d87788c0cea0dc2ecea49ba2f431764ca34..6cb4c2ee49a210b5e1f524e7abcc8bc17c37a68a 100644 GIT binary patch delta 543 zcmX|-%}ZNB5Wr{mZC_qC#`jEOstM5-{Awsj)Cx8sREq~g@QeBfR8hfTXlN;zQv|ACKbW}PRbajq{A~3 zvvQby$D$kwe1Hsm3hRPVEX&7*zKzvfsghsa0YSYO95A6h@sLJys?xE>`3GDR`&m+CEx%7Hqd@4lVK@)MX?pa3U1Ncy~y>3_WE&{Y84Z z=kyBNoZ*jPKVF2-7jLPFJ~s4_ZV)5tZ<2nP4FfIGxxp53qM;TUM32-`XMxB5zyblU z%}{a@teQo({znd8b&N3wue*}AT@UGwLhW*>H1suJ$Jj+wQCypFYs>A delta 282 zcmZn&Y4Dg}z{}471p*8VJR5D_GYbCu|NlP-^8qD5w7_Org~N=SSe7xdvoSC-FflMs zUe9LF$h7%An=~_H57!xMva2Y!HFt7mCF*2-UWMN=tU}OOK?5Yq!vNIB0Mr4*ljXRjCp&VRuuCv%0{JSNYq*6O+5a%^}9f2$TS7<7ePt5?}zj9%Me_<}6V$mdQWl#3oOZ6q>9ee|eKaB{R1< x1A_xlLBppG#>p+pitH|4F