11 Commits

13 changed files with 468 additions and 464 deletions

View File

@ -24,7 +24,7 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>
<name>shared-configuration</name>

View File

@ -15,8 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.muehlencord.shared</groupId>
@ -26,7 +25,7 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>
<name>shared-db</name>
@ -76,7 +75,6 @@ limitations under the License.
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<version>1.18.12</version>
</dependency>
</dependencies>

View File

@ -20,7 +20,7 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>
<groupId>de.muehlencord.shared</groupId>

View File

@ -47,29 +47,29 @@ public abstract class GenericEnumType<T, E extends Enum<E>> implements UserType,
for (E e : enumValues) {
@SuppressWarnings("unchecked")
T value = (T) m.invoke(e);
@SuppressWarnings("unchecked")
T value = (T) m.invoke(e);
enumMap.put(value.toString(), e);
valueMap.put(e, value.toString());
enumMap.put(value.toString(), e);
valueMap.put(e, value.toString());
}
this.sqlType = sqlType;
this.sqlType = sqlType;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
return nullSafeGet(rs, names, owner);
}
@Override
public Object nullSafeGet(ResultSet rs, int index, SharedSessionContractImplementor implementor, Object o) throws SQLException {
return nullSafeGet(rs, index, implementor);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
nullSafeSet(st, value, index);
}
@Override
public Object assemble(Serializable cached, Object owner) {
return cached;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
nullSafeSet(st, value, index);
}
@Override
public Object assemble(Serializable cached, Object owner) {
return cached;
}
@Override
public Object deepCopy(Object obj) {
@ -94,28 +94,28 @@ public abstract class GenericEnumType<T, E extends Enum<E>> implements UserType,
}
}
@Override
public int hashCode(Object obj) {
return obj.hashCode();
}
@Override
public int hashCode(Object obj) {
return obj.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public boolean isMutable() {
return false;
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
String value = rs.getString(names[0]);
if (!rs.wasNull()) {
return enumMap.get(value);
}
return null;
public Object nullSafeGet(ResultSet rs, int index, Object owner) throws SQLException {
String value = rs.getString(index);
if (!rs.wasNull()) {
return enumMap.get(value);
}
return null;
}
public void nullSafeSet(PreparedStatement ps, Object obj, int index) throws SQLException {
if (obj == null) {
ps.setNull(index, sqlType);
} else {
public void nullSafeSet(PreparedStatement ps, Object obj, int index) throws SQLException {
if (obj == null) {
ps.setNull(index, sqlType);
} else {
ps.setObject(index, valueMap.get(obj), sqlType);
}
}
@ -130,9 +130,5 @@ public abstract class GenericEnumType<T, E extends Enum<E>> implements UserType,
return clazz;
}
@Override
public int[] sqlTypes() {
return new int[]{sqlType};
}
}

View File

@ -15,14 +15,14 @@
*/
package de.muehlencord.shared.jeeutil.restexfw;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
*

View File

@ -15,12 +15,12 @@
*/
package de.muehlencord.shared.jeeutil.restexfw;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import java.util.Iterator;
import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
*

View File

@ -15,23 +15,23 @@
*/
package de.muehlencord.shared.jeeutil.restexfw;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.ws.rs.core.Response.Status;
/**
*
* @author Joern Muehlencord (joern@muehlencord.de)
*/
public class ResponseStatusAdapter extends XmlAdapter<String, Response.Status> {
public class ResponseStatusAdapter extends XmlAdapter<String, Status> {
@Override
public String marshal(Response.Status status) throws Exception {
return status.name();
}
@Override
public String marshal(Response.Status status) throws Exception {
return status.name();
}
@Override
public Response.Status unmarshal(String statusAsString) throws Exception {
return Response.Status.valueOf(statusAsString);
}
@Override
public Response.Status unmarshal(String statusAsString) throws Exception {
return Response.Status.valueOf(statusAsString);
}
}

View File

@ -13,8 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>shared-network</artifactId>
<build>
@ -73,7 +72,7 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -81,5 +80,5 @@ limitations under the License.
<url>http://maven.apache.org</url>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</project>

View File

@ -15,8 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>shared-poi-util</artifactId>
<dependencies>
@ -48,9 +47,9 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</project>

View File

@ -1,323 +1,322 @@
/*
* Copyright 2019 Joern Muehlencord (joern@muehlencord.de).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.poi;
import de.muehlencord.shared.util.file.FileUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaRenderer;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.RefPtgBase;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Joern Muehlencord (joern@muehlencord.de)
*/
public class WorkbookApp {
private final static Logger LOGGER = LoggerFactory.getLogger(WorkbookApp.class);
/**
* the workbook to work on
*/
protected Workbook wb;
/**
* opens the given workbook
*
* @param filename path and filename of the workbook to open.
* @return the workbook loaded
* @throws FileNotFoundException if the workbook cannot be found
* @throws IOException if the workbook cannot be loaded
*/
public Workbook loadWorkbook(String filename) throws IOException {
if (filename.toLowerCase().endsWith(".xlsx")) {
FileInputStream fis = new FileInputStream(new File(filename));
return new XSSFWorkbook(fis);
} else {
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename));
return new HSSFWorkbook(fs, true);
}
}
/**
* stores the (changed) workbook under the given filename
*
* @param filename the path and name of the file to store the workbook
* under.
* @throws FileNotFoundException if the path is not found
* @throws IOException if the file cannot be genrated.
*/
public void storeWorkbook(String filename) throws IOException {
FileOutputStream fos = new FileOutputStream(new File(filename));
wb.write(fos);
}
/**
* stores the (changed) workbook under the given filename
*
* @param fileName the path and name of the file to store the workbook
* under.
* @param tempName a temporary name the file is stored under before it is
* renamed to fileName. This is required as POI cannot open and store a
* Workbook under the same name.
* @throws FileNotFoundException if the path is not found
* @throws IOException if the file cannot be generated.
*/
public void storeWorkbook(String fileName, String tempName) throws IOException {
FileOutputStream fos = new FileOutputStream(new File(tempName));
wb.write(fos);
File source = Paths.get(tempName).toFile();
File destination = Paths.get(fileName).toFile();
FileUtil.moveFileTo(source, destination);
}
protected void copyColumn(Sheet oldSheet, int oldColumn, Sheet newSheet, int newColumn) {
int maxRowNum = oldSheet.getLastRowNum();
for (int i = 0; i <= maxRowNum; i++) {
Row currentRow = oldSheet.getRow(i);
if (currentRow != null) {
Cell sourceCell = currentRow.getCell(oldColumn);
Cell destCell = currentRow.createCell(newColumn);
copyCell(sourceCell, destCell, null); // copy to same sheet, cellStyle map not needed
CellRangeAddress oldRegion = getMergedRegion(oldSheet, i, oldColumn);
CellRangeAddress newRegion = getMergedRegion(newSheet, i, newColumn);
if (oldRegion != null && newRegion == null) {
if (oldSheet != newSheet | oldRegion.getFirstColumn() == oldColumn) {
// region starts in this column; create new one
int firstRow = oldRegion.getFirstRow();
int lastRow = oldRegion.getLastRow();
int firstColumn = oldRegion.getFirstColumn() + newColumn - oldColumn;
int lastColumn = oldRegion.getLastColumn() + newColumn - oldColumn;
newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
newSheet.addMergedRegion(newRegion);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Created new merged region {}", newRegion.toString());
}
} else {
// region contains source column, extend column to including new column
Integer mergedRegionIndex = getMergedRegionIndex(oldSheet, oldRegion);
if (mergedRegionIndex != null) {
oldSheet.removeMergedRegion(mergedRegionIndex);
}
int firstRow = oldRegion.getFirstRow();
int lastRow = oldRegion.getLastRow();
int firstColumn = oldRegion.getFirstColumn();
int lastColumn = newColumn;
newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
newSheet.addMergedRegion(newRegion);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updated merged region from {} to ", oldRegion.toString(), newRegion.toString());
}
}
}
}
}
newSheet.setColumnWidth(newColumn, oldSheet.getColumnWidth(oldColumn));
}
protected void copyCell(Cell oldCell, Cell newCell, Map<Integer, CellStyle> styleMap) {
if (oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()) {
newCell.setCellStyle(oldCell.getCellStyle());
} else if (styleMap != null) {
int stHashCode = oldCell.getCellStyle().hashCode();
CellStyle newCellStyle = styleMap.get(stHashCode);
if (newCellStyle == null) {
newCellStyle = newCell.getSheet().getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
styleMap.put(stHashCode, newCellStyle);
}
newCell.setCellStyle(newCellStyle);
}
switch (oldCell.getCellType()) {
case STRING:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case BLANK:
newCell.setCellType(CellType.BLANK);
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
String formula = oldCell.getCellFormula();
XSSFEvaluationWorkbook workbookWrapper = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
/* parse formula */
Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL, 0 /*sheet index*/);
/* re-calculate cell references */
for (Ptg ptg : ptgs) {
//base class for cell reference "things"
if (ptg instanceof RefPtgBase) {
RefPtgBase ref = (RefPtgBase) ptg;
if (ref.isColRelative()) {
ref.setColumn(ref.getColumn() + newCell.getColumnIndex() - oldCell.getColumnIndex());
}
if (ref.isRowRelative()) {
ref.setRow(ref.getRow() + +newCell.getRowIndex() - oldCell.getRowIndex());
}
}
}
formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
newCell.setCellFormula(formula);
break;
default:
break;
}
XSSFSheet sheet = (XSSFSheet) oldCell.getSheet();
// TODO copy conditional formating
// FIXME - does not work, it does not take care about formulas at the moment
/*
XSSFSheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
int countConditionalFormatting = conditionalFormatting.getNumConditionalFormattings();
for (int i = 0; i < countConditionalFormatting; i++) {
XSSFConditionalFormatting currentFormatting = conditionalFormatting.getConditionalFormattingAt(i);
CellRangeAddress[] cellRangeAddresses = currentFormatting.getFormattingRanges();
boolean oldCellHasConditionalFormatting = false;
for (CellRangeAddress currentCellRange : cellRangeAddresses) {
oldCellHasConditionalFormatting = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex());
}
if (oldCellHasConditionalFormatting) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Found conditional formatting for cell {} ", oldCell.getAddress().toString());
}
// add the new cell to the cell rang addresses
CellRangeAddress[] newCellRangeAddresses = new CellRangeAddress[cellRangeAddresses.length+1];
for (int j = 0; j < cellRangeAddresses.length; j++) {
newCellRangeAddresses[j] = cellRangeAddresses[j];
}
newCellRangeAddresses[cellRangeAddresses.length] = new CellRangeAddress (newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex());
currentFormatting.setFormattingRanges(newCellRangeAddresses);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Copied conditional formatting to cell {}", newCell.getAddress().toString());
}
}
}
*/
// SheetConditionalFormatting cf = oldCell.getSheet().getSheetConditionalFormatting();
// copy data constraints
List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
Iterator<XSSFDataValidation> it = dataValidations.iterator();
while (it.hasNext()) {
XSSFDataValidation dataValidation = it.next();
boolean oldCellHasDataValidation = false;
CellRangeAddress[] cellRangeAddresses = dataValidation.getRegions().getCellRangeAddresses();
for (CellRangeAddress currentCellRange : cellRangeAddresses) {
oldCellHasDataValidation = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex());
}
if (oldCellHasDataValidation) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Found data validation for cell {} ", oldCell.getAddress().toString());
}
CellRangeAddressList newCellRangeList = new CellRangeAddressList(newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex());
DataValidation newValidation = dataValidationHelper.createValidation(dataValidation.getValidationConstraint(), newCellRangeList);
sheet.addValidationData(newValidation);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Copied data validation to cell {}", newCell.getAddress().toString());
}
}
}
}
protected CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, int cellNum) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress merged = sheet.getMergedRegion(i);
if (merged.isInRange(rowNum, cellNum)) {
return merged;
}
}
return null;
}
protected Integer getMergedRegionIndex(Sheet sheet, CellRangeAddress mergedRegion) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress merged = sheet.getMergedRegion(i);
if ((merged.getFirstColumn() == mergedRegion.getFirstColumn())
&& (merged.getLastColumn() == mergedRegion.getLastColumn())
&& (merged.getFirstRow() == mergedRegion.getFirstRow())
&& (merged.getLastRow() == mergedRegion.getLastRow())) {
return i;
}
}
return null;
}
protected void autoResizeColumns(Sheet sheet) {
autoResizeColumns(sheet,0);
}
protected void autoResizeColumns(Sheet sheet, int referenceRow) {
int maxColumn = sheet.getRow(referenceRow).getPhysicalNumberOfCells();
for (int currentColumn = 0; currentColumn < maxColumn; currentColumn++) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Auto resize column {}/{}", currentColumn, maxColumn);
}
sheet.autoSizeColumn(currentColumn);
}
}
}
/*
* Copyright 2019 Joern Muehlencord (joern@muehlencord.de).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.muehlencord.shared.poi;
import de.muehlencord.shared.util.file.FileUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaRenderer;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.RefPtgBase;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Joern Muehlencord (joern@muehlencord.de)
*/
public class WorkbookApp {
private final static Logger LOGGER = LoggerFactory.getLogger(WorkbookApp.class);
/**
* the workbook to work on
*/
protected Workbook wb;
/**
* opens the given workbook
*
* @param filename path and filename of the workbook to open.
* @return the workbook loaded
* @throws FileNotFoundException if the workbook cannot be found
* @throws IOException if the workbook cannot be loaded
*/
public Workbook loadWorkbook(String filename) throws IOException {
if (filename.toLowerCase().endsWith(".xlsx")) {
FileInputStream fis = new FileInputStream(new File(filename));
return new XSSFWorkbook(fis);
} else {
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename));
return new HSSFWorkbook(fs, true);
}
}
/**
* stores the (changed) workbook under the given filename
*
* @param filename the path and name of the file to store the workbook
* under.
* @throws FileNotFoundException if the path is not found
* @throws IOException if the file cannot be genrated.
*/
public void storeWorkbook(String filename) throws IOException {
FileOutputStream fos = new FileOutputStream(new File(filename));
wb.write(fos);
}
/**
* stores the (changed) workbook under the given filename
*
* @param fileName the path and name of the file to store the workbook
* under.
* @param tempName a temporary name the file is stored under before it is
* renamed to fileName. This is required as POI cannot open and store a
* Workbook under the same name.
* @throws FileNotFoundException if the path is not found
* @throws IOException if the file cannot be generated.
*/
public void storeWorkbook(String fileName, String tempName) throws IOException {
FileOutputStream fos = new FileOutputStream(new File(tempName));
wb.write(fos);
File source = Paths.get(tempName).toFile();
File destination = Paths.get(fileName).toFile();
FileUtil.moveFileTo(source, destination);
}
protected void copyColumn(Sheet oldSheet, int oldColumn, Sheet newSheet, int newColumn) {
int maxRowNum = oldSheet.getLastRowNum();
for (int i = 0; i <= maxRowNum; i++) {
Row currentRow = oldSheet.getRow(i);
if (currentRow != null) {
Cell sourceCell = currentRow.getCell(oldColumn);
Cell destCell = currentRow.createCell(newColumn);
copyCell(sourceCell, destCell, null); // copy to same sheet, cellStyle map not needed
CellRangeAddress oldRegion = getMergedRegion(oldSheet, i, oldColumn);
CellRangeAddress newRegion = getMergedRegion(newSheet, i, newColumn);
if (oldRegion != null && newRegion == null) {
if (oldSheet != newSheet | oldRegion.getFirstColumn() == oldColumn) {
// region starts in this column; create new one
int firstRow = oldRegion.getFirstRow();
int lastRow = oldRegion.getLastRow();
int firstColumn = oldRegion.getFirstColumn() + newColumn - oldColumn;
int lastColumn = oldRegion.getLastColumn() + newColumn - oldColumn;
newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
newSheet.addMergedRegion(newRegion);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Created new merged region {}", newRegion.toString());
}
} else {
// region contains source column, extend column to including new column
Integer mergedRegionIndex = getMergedRegionIndex(oldSheet, oldRegion);
if (mergedRegionIndex != null) {
oldSheet.removeMergedRegion(mergedRegionIndex);
}
int firstRow = oldRegion.getFirstRow();
int lastRow = oldRegion.getLastRow();
int firstColumn = oldRegion.getFirstColumn();
int lastColumn = newColumn;
newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
newSheet.addMergedRegion(newRegion);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updated merged region from {} to ", oldRegion.toString(), newRegion.toString());
}
}
}
}
}
newSheet.setColumnWidth(newColumn, oldSheet.getColumnWidth(oldColumn));
}
protected void copyCell(Cell oldCell, Cell newCell, Map<Integer, CellStyle> styleMap) {
if (oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()) {
newCell.setCellStyle(oldCell.getCellStyle());
} else if (styleMap != null) {
int stHashCode = oldCell.getCellStyle().hashCode();
CellStyle newCellStyle = styleMap.get(stHashCode);
if (newCellStyle == null) {
newCellStyle = newCell.getSheet().getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
styleMap.put(stHashCode, newCellStyle);
}
newCell.setCellStyle(newCellStyle);
}
switch (oldCell.getCellType()) {
case STRING:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case BLANK:
newCell.setBlank();
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
String formula = oldCell.getCellFormula();
XSSFEvaluationWorkbook workbookWrapper = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
/* parse formula */
Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL, 0 /*sheet index*/);
/* re-calculate cell references */
for (Ptg ptg : ptgs) {
//base class for cell reference "things"
if (ptg instanceof RefPtgBase) {
RefPtgBase ref = (RefPtgBase) ptg;
if (ref.isColRelative()) {
ref.setColumn(ref.getColumn() + newCell.getColumnIndex() - oldCell.getColumnIndex());
}
if (ref.isRowRelative()) {
ref.setRow(ref.getRow() + +newCell.getRowIndex() - oldCell.getRowIndex());
}
}
}
formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
newCell.setCellFormula(formula);
break;
default:
break;
}
XSSFSheet sheet = (XSSFSheet) oldCell.getSheet();
// TODO copy conditional formating
// FIXME - does not work, it does not take care about formulas at the moment
/*
XSSFSheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
int countConditionalFormatting = conditionalFormatting.getNumConditionalFormattings();
for (int i = 0; i < countConditionalFormatting; i++) {
XSSFConditionalFormatting currentFormatting = conditionalFormatting.getConditionalFormattingAt(i);
CellRangeAddress[] cellRangeAddresses = currentFormatting.getFormattingRanges();
boolean oldCellHasConditionalFormatting = false;
for (CellRangeAddress currentCellRange : cellRangeAddresses) {
oldCellHasConditionalFormatting = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex());
}
if (oldCellHasConditionalFormatting) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Found conditional formatting for cell {} ", oldCell.getAddress().toString());
}
// add the new cell to the cell rang addresses
CellRangeAddress[] newCellRangeAddresses = new CellRangeAddress[cellRangeAddresses.length+1];
for (int j = 0; j < cellRangeAddresses.length; j++) {
newCellRangeAddresses[j] = cellRangeAddresses[j];
}
newCellRangeAddresses[cellRangeAddresses.length] = new CellRangeAddress (newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex());
currentFormatting.setFormattingRanges(newCellRangeAddresses);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Copied conditional formatting to cell {}", newCell.getAddress().toString());
}
}
}
*/
// SheetConditionalFormatting cf = oldCell.getSheet().getSheetConditionalFormatting();
// copy data constraints
List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
Iterator<XSSFDataValidation> it = dataValidations.iterator();
while (it.hasNext()) {
XSSFDataValidation dataValidation = it.next();
boolean oldCellHasDataValidation = false;
CellRangeAddress[] cellRangeAddresses = dataValidation.getRegions().getCellRangeAddresses();
for (CellRangeAddress currentCellRange : cellRangeAddresses) {
oldCellHasDataValidation = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex());
}
if (oldCellHasDataValidation) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Found data validation for cell {} ", oldCell.getAddress().toString());
}
CellRangeAddressList newCellRangeList = new CellRangeAddressList(newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex());
DataValidation newValidation = dataValidationHelper.createValidation(dataValidation.getValidationConstraint(), newCellRangeList);
sheet.addValidationData(newValidation);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Copied data validation to cell {}", newCell.getAddress().toString());
}
}
}
}
protected CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, int cellNum) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress merged = sheet.getMergedRegion(i);
if (merged.isInRange(rowNum, cellNum)) {
return merged;
}
}
return null;
}
protected Integer getMergedRegionIndex(Sheet sheet, CellRangeAddress mergedRegion) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress merged = sheet.getMergedRegion(i);
if ((merged.getFirstColumn() == mergedRegion.getFirstColumn())
&& (merged.getLastColumn() == mergedRegion.getLastColumn())
&& (merged.getFirstRow() == mergedRegion.getFirstRow())
&& (merged.getLastRow() == mergedRegion.getLastRow())) {
return i;
}
}
return null;
}
protected void autoResizeColumns(Sheet sheet) {
autoResizeColumns(sheet,0);
}
protected void autoResizeColumns(Sheet sheet, int referenceRow) {
int maxColumn = sheet.getRow(referenceRow).getPhysicalNumberOfCells();
for (int currentColumn = 0; currentColumn < maxColumn; currentColumn++) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Auto resize column {}/{}", currentColumn, maxColumn);
}
sheet.autoSizeColumn(currentColumn);
}
}
}

59
pom.xml
View File

@ -15,12 +15,11 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>shared</artifactId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
<name>shared</name>
<packaging>pom</packaging>
@ -50,9 +49,9 @@ limitations under the License.
</developers>
<scm>
<connection>scm:git:https://jomu.timelord.de/git/jomu/shared/</connection>
<developerConnection>scm:git:https://jomu.timelord.de/git/jomu/shared/</developerConnection>
<tag>HEAD</tag>
<connection>scm:git:git@jomu.timelord.de:jomu/shared.git</connection>
<developerConnection>scm:git:git@jomu.timelord.de:jomu/shared.git</developerConnection>
<tag>v1.3.1</tag>
<url>https://jomu.timelord.de/git/jomu/shared/</url>
</scm>
@ -75,12 +74,26 @@ limitations under the License.
<properties>
<!-- project setup -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>1.7.32</slf4j.version>
<jackson.version>2.13.0</jackson.version>
<slf4j.version>2.0.6</slf4j.version>
<jackson.version>2.14.2</jackson.version>
<shiro.version>1.11.0</shiro.version>
<lombok.version>1.18.26</lombok.version>
<junit.version>5.9.2</junit.version>
<primefaces.version>12.0.0</primefaces.version>
<adminfaces-template.version>1.6.1</adminfaces-template.version>
<omnifaces.version>4.0.1</omnifaces.version>
<poi.version>5.2.3</poi.version>
<commons-net.version>3.9.0</commons-net.version>
<gson.version>2.10.1</gson.version>
<fusionauth.version>5.2.2</fusionauth.version>
<bouncycastle.version>1.70</bouncycastle.version>
<hibernate.version>6.1.7.Final</hibernate.version>
</properties>
<dependencyManagement>
@ -114,7 +127,7 @@ limitations under the License.
<dependency>
<artifactId>commons-net</artifactId>
<groupId>commons-net</groupId>
<version>3.8.0</version>
<version>${commons-net.version}</version>
</dependency>
<dependency>
<artifactId>commons-lang3</artifactId>
@ -155,7 +168,7 @@ limitations under the License.
<dependency>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
<version>2.8.9</version>
<version>${gson.version}</version>
</dependency>
<dependency>
<artifactId>jackson-annotations</artifactId>
@ -177,12 +190,12 @@ limitations under the License.
<dependency>
<artifactId>shiro-core</artifactId>
<groupId>org.apache.shiro</groupId>
<version>1.7.1</version>
<version>${shiro.version}</version>
</dependency>
<dependency>
<artifactId>shiro-web</artifactId>
<groupId>org.apache.shiro</groupId>
<version>1.7.1</version>
<version>${shiro.version}</version>
</dependency>
<dependency>
<artifactId>javaee-api</artifactId>
@ -203,39 +216,39 @@ limitations under the License.
<dependency>
<artifactId>bcprov-jdk15on</artifactId>
<groupId>org.bouncycastle</groupId>
<version>1.68</version>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<artifactId>hibernate-core</artifactId>
<groupId>org.hibernate</groupId>
<type>jar</type>
<version>5.6.3.Final</version>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<artifactId>primefaces</artifactId>
<groupId>org.primefaces</groupId>
<version>10.0.0</version>
<version>${primefaces.version}</version>
</dependency>
<dependency>
<artifactId>admin-template</artifactId>
<groupId>com.github.adminfaces</groupId>
<version>1.3.0</version>
<version>${adminfaces-template.version}</version>
</dependency>
<dependency>
<artifactId>omnifaces</artifactId>
<groupId>org.omnifaces</groupId>
<version>3.4.1</version>
<version>${omnifaces.version}</version>
</dependency>
<dependency>
<artifactId>poi-ooxml</artifactId>
<groupId>org.apache.poi</groupId>
<version>5.2.0</version>
<version>${poi.version}</version>
</dependency>
<dependency>
<artifactId>fusionauth-jwt</artifactId>
<groupId>io.fusionauth</groupId>
<version>4.1.0</version>
<version>${fusionauth.version}</version>
</dependency>
<!-- Dev Tools -->
@ -243,7 +256,7 @@ limitations under the License.
<artifactId>lombok</artifactId>
<groupId>org.projectlombok</groupId>
<scope>provided</scope>
<version>1.18.22</version>
<version>${lombok.version}</version>
</dependency>
<!-- Testing -->
@ -251,7 +264,7 @@ limitations under the License.
<artifactId>junit-jupiter-engine</artifactId>
<groupId>org.junit.jupiter</groupId>
<scope>test</scope>
<version>5.8.2</version>
<version>${junit.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -1,45 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2019 Joern Muehlencord (joern@muehlencord.de).
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.muehlencord.shared</groupId>
<artifactId>shared-shiro-faces</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>de.muehlencord</groupId>
<artifactId>shared</artifactId>
<version>1.2-SNAPSHOT</version>
</parent>
<name>shared-shiro-faces</name>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2019 Joern Muehlencord (joern@muehlencord.de).
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.muehlencord.shared</groupId>
<artifactId>shared-shiro-faces</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>de.muehlencord</groupId>
<artifactId>shared</artifactId>
<version>1.3.1</version>
</parent>
<name>shared-shiro-faces</name>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -26,7 +26,7 @@ limitations under the License.
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.2-SNAPSHOT</version>
<version>1.3.1</version>
</parent>