Commit 9f5998cf authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '148-excel-metadata-controller' into 'master'

Resolve "Excel metadata controller"

Closes #148

See merge request !140
parents 01cedbc7 08b23a64
......@@ -233,6 +233,13 @@
<version>2.3</version>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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 org.genesys.catalog.service;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* The Class MetadataService.
*
* @author Maxym Borodenko
*/
public interface MetadataService {
/**
* generate JSON with Excel metadata
*
* @param file
* @return generated JSON object with Excel metadata
*/
ObjectNode getExcelMetadata(File file) throws IOException;
}
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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 org.genesys.catalog.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
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.xssf.usermodel.XSSFWorkbook;
import org.genesys.catalog.service.MetadataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* The Class MetadataServiceImpl.
*
* @author Maxym Borodenko
*/
@Service
public class MetadataServiceImpl implements MetadataService {
/**
* The Constant LOG.
*/
private static final Logger LOG = LoggerFactory.getLogger(MetadataServiceImpl.class);
/**
* The Constant ROWS_TO_READ.
*/
private static final int ROWS_TO_READ = 10;
private final ObjectMapper mapper = new ObjectMapper();
/**
* {@inheritDoc}
*/
@Override
public ObjectNode getExcelMetadata(final File excelFile) throws IOException {
final ObjectNode mainNode = mapper.createObjectNode();
try (final Workbook workbook = new XSSFWorkbook(excelFile)) {
final ArrayNode sheetsArrayNode = mapper.createArrayNode();
final int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
final Sheet datatypeSheet = workbook.getSheetAt(i);
final Iterator<Row> iterator = datatypeSheet.iterator();
JsonNode headersNode = mapper.createArrayNode();
final ArrayNode rowsNode = mapper.createArrayNode();
while (iterator.hasNext()) {
final Row currentRow = iterator.next();
final Iterator<Cell> cellIterator = currentRow.iterator();
final List<Object> values = cellsValues(cellIterator);
if (currentRow.getRowNum() == 0) {
headersNode = mapper.convertValue(values, JsonNode.class);
}
if (currentRow.getRowNum() < ROWS_TO_READ) {
rowsNode.add(mapper.convertValue(values, JsonNode.class));
} else {
// We reached the rows limit
break;
}
}
final ObjectNode sheetNode = mapper.createObjectNode();
sheetNode.put("name", datatypeSheet.getSheetName());
sheetNode.set("headers", headersNode);
sheetNode.set("rows", rowsNode);
sheetNode.put("rowCount", (datatypeSheet.getLastRowNum() + 1));
sheetsArrayNode.add(sheetNode);
}
// leave metadata blank temporarily
mainNode.set("metadata", mapper.createObjectNode());
mainNode.set("sheets", sheetsArrayNode);
} catch (final IOException | InvalidFormatException e) {
LOG.error("Error writing metadata. {}", e.getMessage());
throw new IOException("Error writing metadata", e);
}
return mainNode;
}
/**
* Get cells values from row
*
* @param cellIterator the cellIterator
* @return the list of cell values from row
*/
private List<Object> cellsValues(final Iterator<Cell> cellIterator) {
final List<Object> list = new ArrayList<>();
while (cellIterator.hasNext()) {
final Cell currentCell = cellIterator.next();
switch (currentCell.getCellTypeEnum()) {
case BLANK:
list.add(null);
break;
case ERROR:
list.add("#ERROR");
break;
case STRING:
list.add(currentCell.getStringCellValue());
break;
case BOOLEAN:
list.add(currentCell.getBooleanCellValue());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(currentCell)) {
list.add(currentCell.getDateCellValue());
} else {
list.add(currentCell.getNumericCellValue());
}
break;
default:
list.add(currentCell.toString());
}
}
return list;
}
}
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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 org.genesys.catalog.server.controller.api.v0;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.genesys.catalog.service.MetadataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* The Class MetadataController.
*
* @author Maxym Borodenko
*/
@RestController
@RequestMapping(MetadataController.API_BASE)
@PreAuthorize("isAuthenticated()")
public class MetadataController {
/**
* The Constant API_BASE.
*/
protected static final String API_BASE = "/api/v0/metadata";
/**
* The Constant LOG.
*/
private static final Logger LOG = LoggerFactory.getLogger(MetadataController.class);
private static final String APPLICATION_OXML_SHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
private static final String APPLICATION_MS_EXCEL = "application/vnd.ms-excel";
@Autowired
private MetadataService metadataService;
@PostMapping(consumes = { "multipart/form-data" })
public ObjectNode metadata(@RequestParam("file") final MultipartFile file) throws IOException {
// TODO store the file to the repository
if (APPLICATION_MS_EXCEL.equals(file.getContentType()) || APPLICATION_OXML_SHEET.equals(file.getContentType())) {
return excelMetadata(file);
} else {
throw new UnsupportedOperationException(file.getContentType());
}
}
@PostMapping(consumes = { APPLICATION_MS_EXCEL, APPLICATION_OXML_SHEET })
public ObjectNode excelMetadata(@RequestBody final MultipartFile file) throws IOException {
LOG.info("Analyzing Excel file {}", file.getOriginalFilename());
final File tempFile = File.createTempFile("metadata", ".xlsx");
try {
FileUtils.copyInputStreamToFile(file.getInputStream(), tempFile);
return metadataService.getExcelMetadata(tempFile);
} finally {
FileUtils.deleteQuietly(tempFile);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment