From 91917a01302c6aeb9f33eaf11af4444b8fb1cad5 Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Thu, 12 Oct 2017 00:37:56 +0100 Subject: [PATCH 1/8] Added Support for JPA Entities export. --- .gitignore | 2 + pom.xml | 16 +++++++ .../java/com/ebay/xcelite/column/Col.java | 8 +++- .../ebay/xcelite/column/ColumnsExtractor.java | 48 ++++++++++++++++++- .../ebay/xcelite/writer/BeanSheetWriter.java | 1 + .../ebay/xcelite/writer/SheetWriterAbs.java | 44 ++++++++++++++++- 6 files changed, 116 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4e247ee..186e4da 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /target /.classpath /.project +.~users.xlsx +users.xlsx diff --git a/pom.xml b/pom.xml index 65eb216..5ae4b0b 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,9 @@ org.apache.maven.plugins maven-javadoc-plugin 2.9.1 + + -Xdoclint:none + attach-javadocs @@ -120,5 +123,18 @@ commons-collections 3.2.1 + + + org.hibernate.javax.persistence + hibernate-jpa-2.0-api + 1.0.1.Final + + + + junit + junit + 4.12 + test + \ No newline at end of file diff --git a/src/main/java/com/ebay/xcelite/column/Col.java b/src/main/java/com/ebay/xcelite/column/Col.java index f4e5afa..45e44a6 100644 --- a/src/main/java/com/ebay/xcelite/column/Col.java +++ b/src/main/java/com/ebay/xcelite/column/Col.java @@ -38,10 +38,16 @@ public Col(String name) { } public Col(String name, String fieldName) { + this(name, fieldName, String.class); + } + + + public Col(String name, String fieldName, Class type) { this.name = name; this.fieldName = fieldName; - type = String.class; + this.type = type; } + @Override public String toString() { diff --git a/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java b/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java index 6c0186e..655b9a1 100644 --- a/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java +++ b/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java @@ -17,11 +17,15 @@ import static org.reflections.ReflectionUtils.withAnnotation; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + import org.reflections.ReflectionUtils; import com.ebay.xcelite.annotate.NoConverterClass; @@ -79,7 +83,7 @@ public void extract() { col.setConverter(annotation.converter()); } columns.add(col); - } + } if (colsOrdering != null) { orderColumns(); @@ -88,6 +92,48 @@ public void extract() { extractAnyColumn(); } + + @SuppressWarnings("unchecked") + public void extractJpa() { + Set idFields = ReflectionUtils.getAllFields(type, withAnnotation(javax.persistence.Id.class)); + Set columnFields = ReflectionUtils.getAllFields(type, withAnnotation(javax.persistence.Column.class)); + Set manyToOneFields = ReflectionUtils.getAllFields(type, withAnnotation(ManyToOne.class)); + + for (Field columnField : idFields) { + javax.persistence.Id annotation = columnField.getAnnotation(javax.persistence.Id.class); + if(annotation == null) continue; + Col col = null; + col = new Col(columnField.getName(), columnField.getName()); + columns.add(col); + } + + for (Field columnField : columnFields) { + javax.persistence.Column annotation = columnField.getAnnotation(javax.persistence.Column.class); + if(annotation == null) continue; + Col col = null; + if (annotation.name().isEmpty()) { + col = new Col(columnField.getName(), columnField.getName()); + } else { + col = new Col(annotation.name(), columnField.getName()); + } + columns.add(col); + } + + for (Field columnField : manyToOneFields) { + ManyToOne annotation = columnField.getAnnotation(ManyToOne.class); + Col col = null; + if(annotation == null) continue; + JoinColumn joinColumn = columnField.getAnnotation(JoinColumn.class); + if (joinColumn.name().isEmpty()) { + col = new Col(columnField.getName(), columnField.getName(), columnField.getType()); + } else { + col = new Col(joinColumn.name(), columnField.getName(), columnField.getType()); + } + columns.add(col); + } + } + + @SuppressWarnings("unchecked") private void extractAnyColumn() { Set anyColumnFields = ReflectionUtils.getAllFields(type, withAnnotation(AnyColumn.class)); diff --git a/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java b/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java index f3593ed..b3857a1 100644 --- a/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java +++ b/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java @@ -46,6 +46,7 @@ public BeanSheetWriter(XceliteSheet sheet, Class type) { super(sheet, true); ColumnsExtractor extractor = new ColumnsExtractor(type); extractor.extract(); + extractor.extractJpa(); columns = extractor.getColumns(); anyColumn = extractor.getAnyColumn(); } diff --git a/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java b/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java index cee2e46..197b149 100644 --- a/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java +++ b/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java @@ -15,8 +15,12 @@ */ package com.ebay.xcelite.writer; +import java.lang.reflect.Field; import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.Id; + import org.apache.poi.ss.usermodel.Cell; import com.ebay.xcelite.sheet.XceliteSheet; @@ -52,11 +56,49 @@ protected void writeToCell(Cell cell, Object fieldValueObj, Class dataType) { || type == Short.class || type == short.class) { cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(Double.valueOf(fieldValueObj.toString())); - } else { + } else if (type == String.class) { cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue(fieldValueObj.toString()); + } else { + Entity entity = type.getAnnotation(Entity.class); + if(entity != null) { + try { + Field[] fields = type.getDeclaredFields(); + Field idField = getIdField(fields); + Object value = null; + if(idField == null && fields.length > 0) { + // TODO : Maybe We should sorts field by name and pick the first one. + // So that the reverse operation can be easy. + idField = fields[0]; // Pick a random field + } + try { + idField.setAccessible(true); + value = idField.get(fieldValueObj); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + if(value == null) value = "NOREF"; + cell.setCellType(Cell.CELL_TYPE_STRING); + cell.setCellValue(value.toString()); + } catch (SecurityException e) { + throw new RuntimeException(e); + } + } } } + +private Field getIdField(Field[] fields) { + Field idField = null; + for (Field field : fields) { + if(field.getAnnotation(Id.class) != null) { + idField = field; + break; + } + } + return idField; +} @Override public void generateHeaderRow(boolean generateHeaderRow) { From 84cebcd1bfbb08ec5f4215d1a6d67a0e95f2eede Mon Sep 17 00:00:00 2001 From: Boris Waguia Date: Thu, 12 Oct 2017 10:48:25 +0100 Subject: [PATCH 2/8] Update readme.md Added instructions how to use boriswaguia/xcelite repository as maven dependency. --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 0e775b7..61e32ed 100644 --- a/README.md +++ b/README.md @@ -238,3 +238,22 @@ Add xcelite as a dependency: 1.0.4 ``` +### OR +Add this repository as dependency, if you want support for Jpa data export. +```xml + + + Github + Github repository + https://raw.github.com/boriswaguia/xcelite/release + + +``` + +```xml + + com.ebay + xcelite + 1.0.5-SNAPSHOT + +``` From f2bc1bc5f22c4477717a1c4a9e3d9b361ed63823 Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Wed, 8 Nov 2017 01:59:34 +0100 Subject: [PATCH 3/8] Improve entity&id scanning and string cell value size --- .../ebay/xcelite/writer/SheetWriterAbs.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java b/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java index 197b149..5162d33 100644 --- a/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java +++ b/src/main/java/com/ebay/xcelite/writer/SheetWriterAbs.java @@ -19,7 +19,6 @@ import java.util.Date; import javax.persistence.Entity; -import javax.persistence.Id; import org.apache.poi.ss.usermodel.Cell; @@ -34,6 +33,7 @@ */ public abstract class SheetWriterAbs implements SheetWriter { + private static final int MAX_EXCEL_CELL_CARACTERS = 32767; protected XceliteSheet sheet; protected boolean writeHeader; @@ -58,17 +58,18 @@ protected void writeToCell(Cell cell, Object fieldValueObj, Class dataType) { cell.setCellValue(Double.valueOf(fieldValueObj.toString())); } else if (type == String.class) { cell.setCellType(Cell.CELL_TYPE_STRING); - cell.setCellValue(fieldValueObj.toString()); + String cellValue = extractStringValue(fieldValueObj); + cell.setCellValue(cellValue); } else { - Entity entity = type.getAnnotation(Entity.class); + Entity entity = type.getAnnotation(javax.persistence.Entity.class); if(entity != null) { try { Field[] fields = type.getDeclaredFields(); Field idField = getIdField(fields); Object value = null; + // If no Id field if(idField == null && fields.length > 0) { - // TODO : Maybe We should sorts field by name and pick the first one. - // So that the reverse operation can be easy. + // TODO : Maybe We should sorts field by name and pick the first one. So that the reverse operation can be easy. idField = fields[0]; // Pick a random field } try { @@ -89,16 +90,31 @@ protected void writeToCell(Cell cell, Object fieldValueObj, Class dataType) { } } -private Field getIdField(Field[] fields) { + /** + * Extract the String value, and shrink it to fix excell string size. + * @param fieldValueObj + * @return + */ + private String extractStringValue(Object fieldValueObj) { + String cellValue = fieldValueObj.toString(); + if(cellValue == null) cellValue = ""; + if(cellValue.length() > MAX_EXCEL_CELL_CARACTERS) { + cellValue = cellValue.substring(0, 32764); + cellValue += "..."; + } + return cellValue; + } + + private Field getIdField(Field[] fields) { Field idField = null; for (Field field : fields) { - if(field.getAnnotation(Id.class) != null) { + if(field.getAnnotation(javax.persistence.Id.class) != null) { idField = field; break; } } return idField; -} + } @Override public void generateHeaderRow(boolean generateHeaderRow) { From 9ca63495f64886828dd3a511f6210280fa2ddd78 Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Wed, 8 Nov 2017 02:14:03 +0100 Subject: [PATCH 4/8] Update version to 1.0.6-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5ae4b0b..6c9f4b7 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.ebay xcelite - 1.0.5-SNAPSHOT + 1.0.6-SNAPSHOT jar xcelite Xcelite is an ORM like Java library which allows you to easily serialize and deserialize Java beans to/from Excel spreadsheets From 8c81ed80e3d2d2fa22e67b0f3557288406d5c1bf Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Thu, 9 Nov 2017 16:31:15 +0100 Subject: [PATCH 5/8] Load referenced ManyToOne entities --- .../ebay/xcelite/column/ColumnsExtractor.java | 15 +++++----- .../ebay/xcelite/reader/BeanSheetReader.java | 29 ++++++++++++++++--- .../com/ebay/xcelite/styles/CellStyles.java | 3 +- .../ebay/xcelite/writer/BeanSheetWriter.java | 6 ++-- src/test/java/tmp | 0 5 files changed, 38 insertions(+), 15 deletions(-) delete mode 100644 src/test/java/tmp diff --git a/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java b/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java index 655b9a1..f2ce899 100644 --- a/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java +++ b/src/main/java/com/ebay/xcelite/column/ColumnsExtractor.java @@ -17,7 +17,6 @@ import static org.reflections.ReflectionUtils.withAnnotation; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.Map; @@ -97,13 +96,13 @@ public void extract() { public void extractJpa() { Set idFields = ReflectionUtils.getAllFields(type, withAnnotation(javax.persistence.Id.class)); Set columnFields = ReflectionUtils.getAllFields(type, withAnnotation(javax.persistence.Column.class)); - Set manyToOneFields = ReflectionUtils.getAllFields(type, withAnnotation(ManyToOne.class)); + Set manyToOneFields = ReflectionUtils.getAllFields(type, withAnnotation(javax.persistence.ManyToOne.class)); for (Field columnField : idFields) { javax.persistence.Id annotation = columnField.getAnnotation(javax.persistence.Id.class); if(annotation == null) continue; Col col = null; - col = new Col(columnField.getName(), columnField.getName()); + col = new Col(columnField.getName(), columnField.getName(), columnField.getType()); columns.add(col); } @@ -112,18 +111,18 @@ public void extractJpa() { if(annotation == null) continue; Col col = null; if (annotation.name().isEmpty()) { - col = new Col(columnField.getName(), columnField.getName()); + col = new Col(columnField.getName(), columnField.getName(), columnField.getType()); } else { - col = new Col(annotation.name(), columnField.getName()); + col = new Col(annotation.name(), columnField.getName(), columnField.getType()); } columns.add(col); } for (Field columnField : manyToOneFields) { - ManyToOne annotation = columnField.getAnnotation(ManyToOne.class); + ManyToOne annotation = columnField.getAnnotation(javax.persistence.ManyToOne.class); Col col = null; if(annotation == null) continue; - JoinColumn joinColumn = columnField.getAnnotation(JoinColumn.class); + JoinColumn joinColumn = columnField.getAnnotation(javax.persistence.JoinColumn.class); if (joinColumn.name().isEmpty()) { col = new Col(columnField.getName(), columnField.getName(), columnField.getType()); } else { @@ -154,7 +153,7 @@ private void extractAnyColumn() { if (annotation.converter() != NoConverterClass.class) { anyColumn.setConverter(annotation.converter()); } - } + } } private void orderColumns() { diff --git a/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java b/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java index bed8edb..f92fd3f 100644 --- a/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java +++ b/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java @@ -63,6 +63,7 @@ public BeanSheetReader(XceliteSheet sheet, Class type) { this.type = type; ColumnsExtractor extractor = new ColumnsExtractor(type); extractor.extract(); + extractor.extractJpa(); columns = extractor.getColumns(); anyColumn = extractor.getAnyColumn(); mapper = new ColumnsMapper(columns); @@ -171,11 +172,31 @@ private void writeToField(Field field, T object, Cell cell, Col column) { .newInstance(); cellValue = converter.deserialize(cellValue); } else { - cellValue = convertToFieldType(cellValue, field.getType()); + cellValue = convertToFieldType(cellValue, field.getType(), column); } } - field.setAccessible(true); - field.set(object, cellValue); + boolean annotationPresent = field.isAnnotationPresent(javax.persistence.ManyToOne.class); + if(!annotationPresent) { + field.setAccessible(true); + field.set(object, cellValue); + } else { + Object instance = field.getType().newInstance(); + Field[] declaredFields = instance.getClass().getDeclaredFields(); + Field idField = null; + for (Field f : declaredFields) { + if(f.isAnnotationPresent(javax.persistence.Id.class)) { + idField = f; + break; + } + } + if(idField == null) idField = declaredFields[0]; + // Set the id field in the instance + idField.setAccessible(true); + idField.set(instance, cellValue); + // Set the object value + field.setAccessible(true); + field.set(object, instance); + } } catch (IllegalAccessException e) { throw new RuntimeException(e); @@ -184,7 +205,7 @@ private void writeToField(Field field, T object, Cell cell, Col column) { } } - private Object convertToFieldType(Object cellValue, Class fieldType) { + private Object convertToFieldType(Object cellValue, Class fieldType, Col column) { String value = String.valueOf(cellValue); if (fieldType == Double.class || fieldType == double.class) { return Double.valueOf(value); diff --git a/src/main/java/com/ebay/xcelite/styles/CellStyles.java b/src/main/java/com/ebay/xcelite/styles/CellStyles.java index cb8a9ad..a3544b9 100644 --- a/src/main/java/com/ebay/xcelite/styles/CellStyles.java +++ b/src/main/java/com/ebay/xcelite/styles/CellStyles.java @@ -22,7 +22,8 @@ public final class CellStyles { - private final String DEFAULT_DATE_FORMAT = "ddd mmm dd hh:mm:ss yyy"; +// private final String DEFAULT_DATE_FORMAT = "ddd mmm dd hh:mm:ss yyy"; + private final String DEFAULT_DATE_FORMAT = "dd/mm/yyyy hh:mm:ss"; private final Workbook wb; private CellStyle boldStyle; diff --git a/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java b/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java index b3857a1..5b749e9 100644 --- a/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java +++ b/src/main/java/com/ebay/xcelite/writer/BeanSheetWriter.java @@ -25,6 +25,7 @@ import java.util.Set; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; import org.reflections.ReflectionUtils; import com.ebay.xcelite.annotate.NoConverterClass; @@ -120,8 +121,9 @@ private void writeToCell(Cell cell, Col col, Object fieldValueObj) { } if (col.getType() == Date.class) { - if (col.getDataFormat() == null) { - cell.setCellStyle(CellStylesBank.get(sheet.getNativeSheet().getWorkbook()).getDateStyle()); + if (col.getDataFormat() == null) { + CellStyle dateStyle = CellStylesBank.get(sheet.getNativeSheet().getWorkbook()).getDateStyle(); + cell.setCellStyle(dateStyle); } } diff --git a/src/test/java/tmp b/src/test/java/tmp deleted file mode 100644 index e69de29..0000000 From 14ee3f383bda24c96af65edbb9b9aedbb5a9fb2f Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Thu, 9 Nov 2017 16:32:05 +0100 Subject: [PATCH 6/8] Releasing v1.0.7-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6c9f4b7..895843d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.ebay xcelite - 1.0.6-SNAPSHOT + 1.0.7-SNAPSHOT jar xcelite Xcelite is an ORM like Java library which allows you to easily serialize and deserialize Java beans to/from Excel spreadsheets From 320ddc31a4cbf53efcf92d9330b0e4519e087d49 Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Fri, 10 Nov 2017 02:39:59 +0100 Subject: [PATCH 7/8] Fix boolean null --- .../java/com/ebay/xcelite/reader/BeanSheetReader.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java b/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java index f92fd3f..94d2f4b 100644 --- a/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java +++ b/src/main/java/com/ebay/xcelite/reader/BeanSheetReader.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; +import org.apache.poi.ss.format.CellFormatType; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.Row; @@ -165,7 +166,10 @@ private void writeToAnyColumnField(Field field, T object, Cell cell, String colu @SuppressWarnings("unchecked") private void writeToField(Field field, T object, Cell cell, Col column) { try { - Object cellValue = readValueFromCell(cell); + Object cellValue = readValueFromCell(cell); + if(cellValue == null && (field.getType() == Boolean.class || field.getType() == boolean.class)) { + cellValue = Boolean.FALSE; + } if (cellValue != null) { if (column.getConverter() != null) { ColumnValueConverter converter = (ColumnValueConverter) column.getConverter() @@ -228,6 +232,9 @@ private Object convertToFieldType(Object cellValue, Class fieldType, Col colu if (fieldType == Date.class) { return DateUtil.getJavaDate(Double.valueOf(value)); } + if(fieldType == Boolean.class || fieldType == boolean.class) { + return Boolean.valueOf(value); + } return value; } From a95d248107861c7d19ccec3284d6786cf267c2b2 Mon Sep 17 00:00:00 2001 From: boriswaguia Date: Fri, 10 Nov 2017 02:44:14 +0100 Subject: [PATCH 8/8] Releasing v 1.0.8-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 895843d..a7dcdc6 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.ebay xcelite - 1.0.7-SNAPSHOT + 1.0.8-SNAPSHOT jar xcelite Xcelite is an ORM like Java library which allows you to easily serialize and deserialize Java beans to/from Excel spreadsheets