Skip to content

Commit

Permalink
Merge 2d71369 into 81f0ab2
Browse files Browse the repository at this point in the history
  • Loading branch information
breucode committed May 6, 2020
2 parents 81f0ab2 + 2d71369 commit 0e8a629
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 78 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<configuration>
<argLine>${add.opens}</argLine>
<argLine>-Djava.awt.headless=true</argLine>
<argLine>-Duser.language=en -Duser.region=US</argLine>
</configuration>
</plugin>

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/poiji/annotation/ExcelProperty.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.poiji.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Indicates, that a field contains an excel property (e.g. author, title, custom properties, ...)
*
* @author breucode
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface ExcelProperty {
/**
* If this value is set, the property will be read from property field with this name instead of your field name.
*
* @return the name of the property field to read from
*/
String propertyName() default "";
}
2 changes: 1 addition & 1 deletion src/main/java/com/poiji/annotation/ExcelUnknownCells.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/**
* This annotations allows you to put every unknown cell (neither mapped by name, nor by index) into a {@code Map<String,String>}
*
* @author Pascal Breuer
* @author breucode
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
Expand Down
60 changes: 58 additions & 2 deletions src/main/java/com/poiji/bind/Poiji.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package com.poiji.bind;

import com.poiji.bind.mapping.PropertyHandler;
import com.poiji.bind.mapping.UnmarshallerHelper;
import com.poiji.exception.IllegalCastException;
import com.poiji.exception.InvalidExcelFileExtension;
import com.poiji.exception.PoijiExcelType;
import com.poiji.exception.PoijiException;
import com.poiji.option.PoijiOptions;
import com.poiji.option.PoijiOptions.PoijiOptionsBuilder;
import com.poiji.util.ExcelFileOpenUtil;
import com.poiji.util.Files;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -40,6 +45,57 @@ public final class Poiji {
private Poiji() {
}

public static <T> T fromExcelProperties(final File file, final Class<T> type) {
return fromExcelProperties(file, type, PoijiOptionsBuilder.settings().build());
}

public static <T> T fromExcelProperties(final InputStream inputStream,
PoijiExcelType excelType,
final Class<T> type) {
return fromExcelProperties(inputStream, excelType, type, PoijiOptionsBuilder.settings().build());
}

public static <T> T fromExcelProperties(final File file, final Class<T> type, final PoijiOptions options) {
String extension = files.getExtension(file.getName());

if (XLSX_EXTENSION.equals(extension)) {
try (OPCPackage open = ExcelFileOpenUtil.openXlsxFile(file, options);
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(open)) {

return PropertyHandler.unmarshal(type, xssfWorkbook.getProperties());

} catch (IOException e) {
throw new PoijiException("Problem occurred while reading data", e);
}
} else if (XLS_EXTENSION.equals(extension)) {
throw new InvalidExcelFileExtension("Reading metadata from (" + extension + "), is not supported");
} else {
throw new InvalidExcelFileExtension("Invalid file extension (" + extension + "), expected .xlsx");
}
}

public static <T> T fromExcelProperties(final InputStream inputStream,
PoijiExcelType excelType,
final Class<T> type,
PoijiOptions options) {
Objects.requireNonNull(excelType);

if (excelType == PoijiExcelType.XLSX) {
try (OPCPackage open = ExcelFileOpenUtil.openXlsxFile(inputStream, options);
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(open)) {

return PropertyHandler.unmarshal(type, xssfWorkbook.getProperties());

} catch (IOException e) {
throw new PoijiException("Problem occurred while reading data", e);
}
} else if (excelType == PoijiExcelType.XLS) {
throw new InvalidExcelFileExtension("Reading metadata from (" + excelType + "), is not supported");
} else {
throw new InvalidExcelFileExtension("Invalid file extension (" + excelType + "), expected .xlsx");
}
}

/**
* converts excel rows into a list of objects
*
Expand Down Expand Up @@ -218,7 +274,7 @@ private static Unmarshaller deserializer(final File file, final PoijiOptions opt
} else if (XLSX_EXTENSION.equals(extension)) {
return UnmarshallerHelper.XSSFInstance(poijiFile, options);
} else {
throw new InvalidExcelFileExtension("Invalid file extension (" + extension + "), excepted .xls or .xlsx");
throw new InvalidExcelFileExtension("Invalid file extension (" + extension + "), expected .xls or .xlsx");
}
}

Expand All @@ -230,7 +286,7 @@ private static Unmarshaller deserializer(final InputStream inputStream, PoijiExc
} else if (excelType == PoijiExcelType.XLSX) {
return UnmarshallerHelper.XSSFInstance(poijiInputStream, options);
} else {
throw new InvalidExcelFileExtension("Invalid file extension (" + excelType + "), excepted .xls or .xlsx");
throw new InvalidExcelFileExtension("Invalid file extension (" + excelType + "), expected .xls or .xlsx");
}
}

Expand Down
23 changes: 7 additions & 16 deletions src/main/java/com/poiji/bind/mapping/PoijiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private boolean setValue(String content, Class<? super T> type, int column) {
ExcelRow excelRow = field.getAnnotation(ExcelRow.class);
if (excelRow != null) {
Object o = casting.castValue(field.getType(), valueOf(internalRow), internalRow, column, options);
setFieldData(field, o, instance);
ReflectUtil.setFieldData(field, o, instance);
columnToField.put(-1, field);
}
ExcelCellRange range = field.getAnnotation(ExcelCellRange.class);
Expand All @@ -99,7 +99,7 @@ private boolean setValue(String content, Class<? super T> type, int column) {
ins = getInstance(field);
for (Field f : field.getType().getDeclaredFields()) {
if (setValue(f, column, content, ins)) {
setFieldData(field, ins, instance);
ReflectUtil.setFieldData(field, ins, instance);
columnToField.put(column, f);
columnToSuperClassField.put(column, field);
}
Expand All @@ -119,7 +119,7 @@ private boolean setValue(String content, Class<? super T> type, int column) {
field.setAccessible(true);
if (field.get(instance) == null) {
excelUnknownCellsMap = new HashMap<>();
setFieldData(field, excelUnknownCellsMap, instance);
ReflectUtil.setFieldData(field, excelUnknownCellsMap, instance);
} else {
excelUnknownCellsMap = (Map) field.get(instance);
}
Expand All @@ -133,14 +133,14 @@ private boolean setValue(String content, Class<? super T> type, int column) {
if (columnToField.containsKey(-1)) {
Field field = columnToField.get(-1);
Object o = casting.castValue(field.getType(), valueOf(internalRow), internalRow, column, options);
setFieldData(field, o, instance);
ReflectUtil.setFieldData(field, o, instance);
}
if (columnToField.containsKey(column) && columnToSuperClassField.containsKey(column)) {
Field field = columnToField.get(column);
Object ins;
ins = getInstance(columnToSuperClassField.get(column));
if (setValue(field, column, content, ins)) {
setFieldData(columnToSuperClassField.get(column), ins, instance);
ReflectUtil.setFieldData(columnToSuperClassField.get(column), ins, instance);
return true;
}
return setValue(field, column, content, instance);
Expand All @@ -154,7 +154,7 @@ private boolean setValue(Field field, int column, String content, Object ins) {
Class<?> fieldType = field.getType();
if (column == index.value()) {
Object o = casting.castValue(fieldType, content, internalRow, column, options);
setFieldData(field, o, ins);
ReflectUtil.setFieldData(field, o, ins);
return true;
}
} else {
Expand All @@ -169,23 +169,14 @@ private boolean setValue(Field field, int column, String content, Object ins) {
//Fix both columns mapped to name passing this condition below
if (titleColumn != null && titleColumn == column) {
Object o = casting.castValue(fieldType, content, internalRow, column, options);
setFieldData(field, o, ins);
ReflectUtil.setFieldData(field, o, ins);
return true;
}
}
}
return false;
}

private void setFieldData(Field field, Object o, Object instance) {
try {
field.setAccessible(true);
field.set(instance, o);
} catch (IllegalAccessException e) {
throw new IllegalCastException("Unexpected cast type {" + o + "} of field" + field.getName());
}
}

@Override
public void startRow(int rowNum) {
if (rowNum + 1 > options.skip()) {
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/poiji/bind/mapping/PropertyHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.poiji.bind.mapping;

import com.poiji.annotation.ExcelProperty;
import com.poiji.util.ReflectUtil;
import org.apache.poi.ooxml.POIXMLProperties;

import java.lang.reflect.Field;
import java.util.stream.Stream;

public final class PropertyHandler {

public static <T> T unmarshal(Class<T> type, POIXMLProperties poixmlProperties) {

T unmarshalledObject = ReflectUtil.newInstanceOf(type);

Stream.of(type.getDeclaredFields())
.filter(field -> field.getAnnotation(ExcelProperty.class) != null)
.forEach(excelPropertyField -> {
String propertyName = getPropertyName(excelPropertyField);

setPropertyValueOnTarget(propertyName, poixmlProperties, excelPropertyField, unmarshalledObject);
});

return unmarshalledObject;
}

private static String getPropertyName(Field excelPropertyField) {
String propertyName = excelPropertyField.getAnnotation(ExcelProperty.class).propertyName();

if (propertyName.isEmpty()) {
propertyName = excelPropertyField.getName();
}

return propertyName;
}

private static void setPropertyValueOnTarget(String propertyName, POIXMLProperties poixmlProperties, Field targetField, Object targetObject) {
switch (propertyName) {
case "category":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getCategory(), targetObject);
break;
case "contentStatus":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getContentStatus(), targetObject);
break;
case "created":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getCreated(), targetObject);
break;
case "creator":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getCreator(), targetObject);
break;
case "description":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getDescription(), targetObject);
break;
case "keywords":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getKeywords(), targetObject);
break;
case "lastPrinted":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getLastPrinted(), targetObject);
break;
case "modified":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getModified(), targetObject);
break;
case "subject":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getSubject(), targetObject);
break;
case "title":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getTitle(), targetObject);
break;
case "revision":
ReflectUtil.setFieldData(targetField, poixmlProperties.getCoreProperties().getRevision(), targetObject);
break;
default:
if (poixmlProperties.getCustomProperties().getProperty(propertyName) != null) {
ReflectUtil.setFieldData(targetField, poixmlProperties.getCustomProperties().getProperty(propertyName).getLpwstr(), targetObject);
}

break;
}
}
}
16 changes: 0 additions & 16 deletions src/main/java/com/poiji/bind/mapping/XSSFUnmarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import com.poiji.option.PoijiOptions;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.XMLHelper;
Expand Down Expand Up @@ -124,19 +122,5 @@ private <T> void processSheet(StylesTable styles,
}
}

protected <T> void listOfEncryptedItems(Class<T> type, Consumer<? super T> consumer, POIFSFileSystem fs) throws IOException {
InputStream stream = DocumentFactoryHelper.getDecryptedStream(fs, options.getPassword());

try (OPCPackage open = OPCPackage.open(stream)) {
unmarshal0(type, consumer, open);

} catch (ParserConfigurationException | SAXException | IOException | OpenXML4JException e) {
IOUtils.closeQuietly(fs);
throw new PoijiException("Problem occurred while reading data", e);
}
}

protected abstract <T> void returnFromExcelFile(Class<T> type, Consumer<? super T> consumer);

protected abstract <T> void returnFromEncryptedFile(Class<T> type, Consumer<? super T> consumer);
}
23 changes: 3 additions & 20 deletions src/main/java/com/poiji/bind/mapping/XSSFUnmarshallerFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import com.poiji.bind.PoijiFile;
import com.poiji.exception.PoijiException;
import com.poiji.option.PoijiOptions;
import com.poiji.util.ExcelFileOpenUtil;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
Expand All @@ -28,33 +27,17 @@ final class XSSFUnmarshallerFile extends XSSFUnmarshaller {
@Override
public <T> void unmarshal(Class<T> type, Consumer<? super T> consumer) {

if (options.getPassword() != null) {
returnFromEncryptedFile(type, consumer);
return;
}
returnFromExcelFile(type,consumer);
returnFromExcelFile(type, consumer);
}

public <T> void returnFromExcelFile(Class<T> type, Consumer<? super T> consumer) {

try (OPCPackage open = OPCPackage.open(poijiFile.file(), PackageAccess.READ)) {
try (OPCPackage open = ExcelFileOpenUtil.openXlsxFile(poijiFile.file(), options)) {

unmarshal0(type, consumer, open);

} catch (ParserConfigurationException | SAXException | IOException | OpenXML4JException e) {
throw new PoijiException("Problem occurred while reading data", e);
}
}

public <T> void returnFromEncryptedFile(Class<T> type, Consumer<? super T> consumer) {

try (POIFSFileSystem fs = new POIFSFileSystem(poijiFile.file(), true)) {

listOfEncryptedItems(type, consumer, fs);

} catch (IOException e) {
throw new PoijiException("Problem occurred while reading data", e);
}
}

}
Loading

0 comments on commit 0e8a629

Please sign in to comment.