From 36cae3ab14d141ef65522305a47007fde8528035 Mon Sep 17 00:00:00 2001 From: gallenc Date: Tue, 23 May 2023 12:34:01 +0100 Subject: [PATCH 01/15] csv file reading capability added --- .../opennms-pris-plugins-xls/pom.xml | 5 + .../pris/plugins/xls/source/XlsSource.java | 300 +++++++++++------- .../plugins/xls/source/XlsSourceTest.java | 211 ++++++++---- .../src/test/resources/testcsv-noheaders.csv | 3 + .../src/test/resources/testcsv.csv | 4 + pom.xml | 1 + 6 files changed, 355 insertions(+), 169 deletions(-) create mode 100644 opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv-noheaders.csv create mode 100644 opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv.csv diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml b/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml index 9a7cf9e8..34ff8647 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml @@ -31,6 +31,11 @@ poi-ooxml ${apachePoiVersion} + + org.apache.commons + commons-lang3 + ${commonsLang3Version} + ${project.groupId} diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java b/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java index 782cd3d1..968d05a8 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java @@ -19,8 +19,11 @@ */ package org.opennms.opennms.pris.plugins.xls.source; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; @@ -28,11 +31,18 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import org.apache.commons.lang3.math.NumberUtils; + import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -57,12 +67,17 @@ public class XlsSource implements Source { - private static final Logger LOGGER = LoggerFactory - .getLogger(XlsSource.class); + private static final Logger LOGGER = LoggerFactory.getLogger(XlsSource.class); private final InstanceConfiguration config; + private final String csvHeaders; + private final String WITHIN_SPLITTER = ","; + + // note that the csv file is delimited by ',' but multiple services must be delimited by ';' in cells + private final String CSV_FILE_DELIMITER = ","; + private final String CSV_FILE_WITHIN_SPLITTER = ";"; private final String PREFIX_FOR_ASSETS = "Asset_"; private final String PREFIX_FOR_METADATA = "MetaData_"; @@ -76,69 +91,137 @@ public class XlsSource implements Source { private Map assetColumns; private Map> metaDataColumns; - private File xls; private final String encoding; public static String getStringValueFromCell(Cell cell) { String value = null; switch (cell.getCellTypeEnum()) { - case NUMERIC: - double d = cell.getNumericCellValue(); - if (d % 1 ==0) { - value = Integer.toString((int) d); - } else { - // prints double with 7 decimal places - suitable for lat/long - value = String.format("%.7f",d); - } - break; - case STRING: value = cell.getStringCellValue(); - break; - case BOOLEAN: value = ((Boolean) cell.getBooleanCellValue()).toString(); - break; - default: break; + case NUMERIC: + double d = cell.getNumericCellValue(); + if (d % 1 == 0) { + value = Integer.toString((int) d); + } else { + // prints double with 7 decimal places - suitable for lat/long + value = String.format("%.7f", d); + } + break; + case STRING: + value = cell.getStringCellValue(); + break; + case BOOLEAN: + value = ((Boolean) cell.getBooleanCellValue()).toString(); + break; + default: + break; } - - return value; + + return value; } public static Integer getIntValueFromCell(Cell cell) { Integer value = null; switch (cell.getCellTypeEnum()) { - case NUMERIC: value = (int)cell.getNumericCellValue(); - break; - case STRING: value = Integer.getInteger(cell.getStringCellValue()); - break; - default: break; + case NUMERIC: + value = (int) cell.getNumericCellValue(); + break; + case STRING: + value = Integer.getInteger(cell.getStringCellValue()); + break; + default: + break; } - - return value; + + return value; } public XlsSource(final InstanceConfiguration config) { this.config = config; this.encoding = config.getString("encoding", "ISO-8859-1"); + + this.csvHeaders = config.getString("org.opennms.pris.spreadsheet.fields"); } - public static Workbook getWorkbook(File file) { - + public Workbook getWorkbook(File file) { + + // if file is csv file then create spreadsheet in workbook from lines in csv file. + String fileName = file.getName(); + String extension = null; + int i = fileName.lastIndexOf('.'); + if (i > 0) { + extension = fileName.substring(i + 1); + fileName = fileName.substring(0, i); + } + + if ("csv".equals(extension)) { + try { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet(fileName); + + // if headers provided as a property then create first row of spreadsheet with + // headers + int rowNum = 0; + if (csvHeaders != null) { + String[] headers = csvHeaders.split(CSV_FILE_DELIMITER); + + HSSFRow firstRow = sheet.createRow(rowNum); + for (int headercount = 0; headercount < headers.length; headercount++) { + HSSFCell cell = firstRow.createCell(headercount); + cell.setCellValue(headers[headercount].trim()); + } + rowNum++; + } + + // create rest of spreadsheet with csv data in file see + // https://javacodepoint.com/java-code-convert-csv-to-excel-file-using-apache-poi/ + BufferedReader br = new BufferedReader(new FileReader(file)); + String nextLine; + while ((nextLine = br.readLine()) != null) { + Row currentRow = sheet.createRow(rowNum); + + String rowData[] = nextLine.split(CSV_FILE_DELIMITER); + for (int column = 0; column < rowData.length; column++) { + if (NumberUtils.isDigits(rowData[column])) { + currentRow.createCell(column).setCellValue(Integer.parseInt(rowData[column].trim())); + // isCreatable same as deprecated isNumber + } else if (NumberUtils.isCreatable(rowData[column])) { + currentRow.createCell(column).setCellValue(Double.parseDouble(rowData[column].trim())); + } else { + // String values we always substitute SPLITTERS + String stringCellData = rowData[column].trim().replace(CSV_FILE_WITHIN_SPLITTER, WITHIN_SPLITTER); + //TODO REMOVE + System.out.println("rowNum "+rowNum + " column "+column+ " "+stringCellData); + Cell cell = currentRow.createCell(column); + cell.setCellValue(stringCellData); + } + } + + rowNum++; + } + return workbook; + + } catch (Exception ex) { + LOGGER.error("can not create workbook from csv file {}", file.getAbsolutePath(), ex); + return null; + } + } + + // for normal excel spreadsheet read file try { return new XSSFWorkbook(new FileInputStream(file)); } catch (Exception e) { try { return new HSSFWorkbook(new FileInputStream(file)); } catch (Exception e1) { - LOGGER.error("can not create workbook from file {}", - file.getAbsolutePath(), e); - LOGGER.error("can not create workbook from file {}", - file.getAbsolutePath(), e1); - } + LOGGER.error("can not create workbook from file {}", file.getAbsolutePath(), e); + LOGGER.error("can not create workbook from file {}", file.getAbsolutePath(), e1); + } } return null; } - + @Override public Object dump() throws MissingRequiredColumnHeaderException, Exception { final String instance = this.config.getInstanceIdentifier(); @@ -151,21 +234,18 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { sheetNames.add(workbook.getSheetName(i)); } if (!sheetNames.contains(instance)) { - LOGGER.error("can not find sheet {} in workbook from file {}", - instance, xls.getAbsolutePath()); + LOGGER.error("can not find sheet {} in workbook from file {}", instance, xls.getAbsolutePath()); workbook.close(); - throw new RuntimeException("can not find sheet " + instance - + " in workbook from file " + xls.getAbsolutePath()); + throw new RuntimeException( + "can not find sheet " + instance + " in workbook from file " + xls.getAbsolutePath()); } - + Sheet sheet = workbook.getSheet(instance); if (sheet == null) { - LOGGER.error( - "can not read sheet {} in workbook from file {} check the configured encoding {}", - instance, xls.getAbsolutePath(), encoding); + LOGGER.error("can not read sheet {} in workbook from file {} check the configured encoding {}", instance, + xls.getAbsolutePath(), encoding); workbook.close(); - throw new RuntimeException("can not read sheet " + instance - + " from file " + xls.getAbsolutePath() + throw new RuntimeException("can not read sheet " + instance + " from file " + xls.getAbsolutePath() + " check the encoding " + encoding + "."); } @@ -180,7 +260,7 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { if (rowiterator.hasNext()) { rowiterator.next(); } - Map nodeLabelRequisitionNodeMap = new HashMap<>(); + Map nodeLabelRequisitionNodeMap = new HashMap<>(); while (rowiterator.hasNext()) { Row row = rowiterator.next(); Cell cell = getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_NODE); @@ -188,14 +268,14 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { continue; } String nodeLabel = XlsSource.getStringValueFromCell(cell); - RequisitionNode node = new RequisitionNode(); + RequisitionNode node = new RequisitionNode(); if (nodeLabelRequisitionNodeMap.containsKey(nodeLabel)) { - node = nodeLabelRequisitionNodeMap.get(nodeLabel); + node = nodeLabelRequisitionNodeMap.get(nodeLabel); } else { - node.setNodeLabel(nodeLabel); - node.setForeignId(nodeLabel); - nodeLabelRequisitionNodeMap.put(nodeLabel, node); - requisition.getNodes().add(node); + node.setNodeLabel(nodeLabel); + node.setForeignId(nodeLabel); + nodeLabelRequisitionNodeMap.put(nodeLabel, node); + requisition.getNodes().add(node); } cell = getRelevantColumnID(row, OPTIONAL_UNIQUE_HEADERS.PREFIX_FOREIGN_ID); @@ -210,6 +290,8 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { // adding parent data cell = getRelevantColumnID(row, OPTIONAL_UNIQUE_HEADERS.PREFIX_PARENT_FOREIGN_SOURCE); + //TODO REMOVE + System.out.println("xxx foreign source: "+OPTIONAL_UNIQUE_HEADERS.PREFIX_PARENT_FOREIGN_SOURCE+" "+ cell); if (cell != null) { node.setParentForeignSource(XlsSource.getStringValueFromCell(cell)); } @@ -240,8 +322,7 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { node.getInterfaces().add(reqInterface); } workbook.close(); - LOGGER.info("xls source delivered for requisition '{}' '{}' nodes", - instance, requisition.getNodes().size()); + LOGGER.info("xls source delivered for requisition '{}' '{}' nodes", instance, requisition.getNodes().size()); return requisition; } @@ -250,29 +331,36 @@ private Cell getRelevantColumnID(Row row, REQUIRED_UNIQUE_PREFIXES prefix) { } private Cell getRelevantColumnID(Row row, OPTIONAL_UNIQUE_HEADERS header) { + //TODO REMOVE + System.out.println("header.HEADER:"+header.HEADER); + System.out.print("header.HEADER bytes:"); + byte[] a = header.HEADER.getBytes(); + for(int i=0; i< a.length ; i++) { + System.out.print(a[i] +" "); + } + System.out.println(); + for(Entry entry: optionalUniquHeaders.entrySet()) { + System.out.println(" optionalUniquHeaders:"+entry); + } Integer columnId = optionalUniquHeaders.get(header.HEADER); - if ( columnId == null ) { + if (columnId == null) { return null; } return row.getCell(columnId); } - private List getRelevantColumnIDs( - OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES prefix) { + private List getRelevantColumnIDs(OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES prefix) { return optionalMultiColumns.get(prefix.PREFIX); } - private Map initializeRequiredColumns(Sheet sheet) - throws MissingRequiredColumnHeaderException { + private Map initializeRequiredColumns(Sheet sheet) throws MissingRequiredColumnHeaderException { Map result = new HashMap<>(); - for (REQUIRED_UNIQUE_PREFIXES prefix : REQUIRED_UNIQUE_PREFIXES - .values()) { + for (REQUIRED_UNIQUE_PREFIXES prefix : REQUIRED_UNIQUE_PREFIXES.values()) { Row row = sheet.getRow(0); Iterator celliterator = row.cellIterator(); while (celliterator.hasNext()) { Cell cell = celliterator.next(); - if (cell.getStringCellValue().toLowerCase() - .startsWith(prefix.PREFIX.toLowerCase())) { + if (cell.getStringCellValue().toLowerCase().startsWith(prefix.PREFIX.toLowerCase())) { result.put(prefix.PREFIX, cell.getColumnIndex()); } } @@ -285,13 +373,31 @@ private Map initializeRequiredColumns(Sheet sheet) private Map initializeOptionalUniquHeaders(Sheet sheet) { Map result = new HashMap<>(); + System.out.println("****************** Start initialise Unique headers"); for (OPTIONAL_UNIQUE_HEADERS header : OPTIONAL_UNIQUE_HEADERS.values()) { Row row = sheet.getRow(0); Iterator celliterator = row.cellIterator(); while (celliterator.hasNext()) { Cell cell = celliterator.next(); - if (cell.getStringCellValue().toLowerCase() - .startsWith(header.HEADER.toLowerCase())) { + //TODO remove + System.out.println("initialise Optional: "+cell.getStringCellValue()+" "+cell.getStringCellValue().toLowerCase()+" "+header.HEADER.toLowerCase()); + System.out.print("header.HEADER bytes: "); + byte[] a = header.HEADER.toLowerCase().getBytes(); + for(int i=0; i< a.length ; i++) { + System.out.print(a[i] +" "); + } + System.out.println(" header: "+ new String(a, StandardCharsets.UTF_8)); + System.out.print("cell value bytes: "); + byte[] b = cell.getStringCellValue().toLowerCase().getBytes(); + for(int i=0; i< b.length ; i++) { + System.out.print(b[i] +" "); + } + System.out.println(" cell: "+ new String(b, StandardCharsets.UTF_8)); + + + + if (cell.getStringCellValue().toLowerCase().startsWith(header.HEADER.toLowerCase())) { + System.out.println("put header : "+header.HEADER+" cell index: "+cell.getColumnIndex() ); result.put(header.HEADER, cell.getColumnIndex()); } } @@ -299,17 +405,14 @@ private Map initializeOptionalUniquHeaders(Sheet sheet) { return result; } - private Map> initializeOptionalMultiColumns( - Sheet sheet) { + private Map> initializeOptionalMultiColumns(Sheet sheet) { Map> result = new HashMap<>(); - for (OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES prefix : OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES - .values()) { + for (OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES prefix : OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES.values()) { Row row = sheet.getRow(0); Iterator celliterator = row.cellIterator(); while (celliterator.hasNext()) { Cell cell = celliterator.next(); - if (cell.getStringCellValue().toLowerCase() - .startsWith(prefix.PREFIX.toLowerCase())) { + if (cell.getStringCellValue().toLowerCase().startsWith(prefix.PREFIX.toLowerCase())) { if (result.containsKey(prefix.PREFIX)) { result.get(prefix.PREFIX).add(cell.getColumnIndex()); } else { @@ -348,8 +451,7 @@ private Map initializeAssetColumns(Sheet sheet) { Iterator celliterator = row.cellIterator(); while (celliterator.hasNext()) { Cell cell = celliterator.next(); - if (cell.getStringCellValue().toLowerCase() - .equalsIgnoreCase(PREFIX_FOR_ASSETS + prefix.name)) { + if (cell.getStringCellValue().toLowerCase().equalsIgnoreCase(PREFIX_FOR_ASSETS + prefix.name)) { if (result.containsKey(prefix.name)) { result.put(prefix.name, cell.getColumnIndex()); } else { @@ -398,13 +500,11 @@ private Set getServicesByRow(Row row) { if (value == null) { continue; } - String rawServices = value - .trim(); + String rawServices = value.trim(); for (String service : rawServices.split(WITHIN_SPLITTER)) { service = service.trim(); if (!service.isEmpty()) { - services.add(new RequisitionMonitoredService() - .withServiceName(service)); + services.add(new RequisitionMonitoredService().withServiceName(service)); } } } @@ -452,34 +552,25 @@ private Set getMetaDataByRow(Row row) { return metaData; } - private RequisitionInterface getInterfaceByRow(Row row) - throws InvalidInterfaceException { + private RequisitionInterface getInterfaceByRow(Row row) throws InvalidInterfaceException { RequisitionInterface reqInterface = new RequisitionInterface(); - String ip = XlsSource.getStringValueFromCell(getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_IP_ADDRESS)); + String ip = XlsSource + .getStringValueFromCell(getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_IP_ADDRESS)); if (ip == null) { - throw new InvalidInterfaceException( - "Null IP-Address for node '" - + getRelevantColumnID(row,REQUIRED_UNIQUE_PREFIXES.PREFIX_NODE) - .getStringCellValue().trim() - + "' at row '" - + row.getRowNum(), null - ); + throw new InvalidInterfaceException("Null IP-Address for node '" + + getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_NODE).getStringCellValue().trim() + + "' at row '" + row.getRowNum(), null); } try { - reqInterface - .setIpAddr(ip.trim()); + reqInterface.setIpAddr(ip.trim()); } catch (IllegalArgumentException ex) { - throw new InvalidInterfaceException( - "Invalid IP-Address for node '" - + getRelevantColumnID(row,REQUIRED_UNIQUE_PREFIXES.PREFIX_NODE) - .getStringCellValue().trim() - + "' at row '" - + row.getRowNum() - + "' and IP '" - + ip.trim() + "'", ex); + throw new InvalidInterfaceException("Invalid IP-Address for node '" + + getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_NODE).getStringCellValue().trim() + + "' at row '" + row.getRowNum() + "' and IP '" + ip.trim() + "'", ex); } - - String interfaceType = XlsSource.getStringValueFromCell(getRelevantColumnID(row,REQUIRED_UNIQUE_PREFIXES.PREFIX_INTERFACE_MANGEMENT_TYPE)).trim(); + + String interfaceType = XlsSource.getStringValueFromCell( + getRelevantColumnID(row, REQUIRED_UNIQUE_PREFIXES.PREFIX_INTERFACE_MANGEMENT_TYPE)).trim(); if (interfaceType.equalsIgnoreCase(INTERFACE_TYPE_PRIMARY)) { reqInterface.setSnmpPrimary(PrimaryType.PRIMARY); } else if (interfaceType.equalsIgnoreCase(INTERFACE_TYPE_SECONDARY)) { @@ -487,7 +578,7 @@ private RequisitionInterface getInterfaceByRow(Row row) } else { reqInterface.setSnmpPrimary(PrimaryType.NOT_ELIGIBLE); } - + Cell cell = getRelevantColumnID(row, OPTIONAL_UNIQUE_HEADERS.PREFIX_INTERFACE_STATUS); if (cell != null) { Integer value = XlsSource.getIntValueFromCell(cell); @@ -521,8 +612,7 @@ public void setXlsFile(File xls) { */ private enum REQUIRED_UNIQUE_PREFIXES { - PREFIX_NODE("Node_"), PREFIX_IP_ADDRESS("IP_"), PREFIX_INTERFACE_MANGEMENT_TYPE( - "MgmtType_"); + PREFIX_NODE("Node_"), PREFIX_IP_ADDRESS("IP_"), PREFIX_INTERFACE_MANGEMENT_TYPE("MgmtType_"); private final String PREFIX; @@ -552,11 +642,9 @@ private OPTIONAL_MULTIPLE_SPLITCONTENT_PREFIXES(String prefix) { * They can just be used for one column. */ private enum OPTIONAL_UNIQUE_HEADERS { - PREFIX_INTERFACE_STATUS("InterfaceStatus"), PREFIX_FOREIGN_ID("ID_"), PREFIX_LOCATION( - "Location"), PREFIX_PARENT_FOREIGN_SOURCE( - "Parent_Foreign_Source"), PREFIX_PARENT_FOREIGN_ID( - "Parent_Foreign_Id"), PREFIX_PARENT_NODE_LABEL( - "Parent_Node_Label"); + PREFIX_INTERFACE_STATUS("InterfaceStatus"), PREFIX_FOREIGN_ID("ID_"), PREFIX_LOCATION("Location"), + PREFIX_PARENT_FOREIGN_SOURCE("Parent_Foreign_Source"), PREFIX_PARENT_FOREIGN_ID("Parent_Foreign_Id"), + PREFIX_PARENT_NODE_LABEL("Parent_Node_Label"); private final String HEADER; diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java index 52b806aa..f1926290 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java @@ -1,5 +1,7 @@ package org.opennms.opennms.pris.plugins.xls.source; +import java.io.File; +import java.io.FileOutputStream; import java.nio.file.Paths; import static org.hamcrest.Matchers.contains; @@ -7,6 +9,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import org.apache.poi.ss.usermodel.Workbook; import org.junit.Before; import org.junit.Test; import org.opennms.pris.api.MockInstanceConfiguration; @@ -20,69 +23,151 @@ import org.opennms.pris.model.RequisitionNode; import org.opennms.pris.util.RequisitionUtils; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + public class XlsSourceTest { - private XlsSource xlsSource; - - @Before - public void setUp() { - MockInstanceConfiguration config = new MockInstanceConfiguration("test"); - config.set("encoding", "ISO-8859-1"); - config.set("file", Paths.get("src/test/resources/test.xls")); - - xlsSource = new XlsSource(config); - } - - @Test - public void basicTest() throws Exception { - Requisition resultRequisition = (Requisition) xlsSource.dump(); - - assertEquals(resultRequisition.getForeignSource(), "test"); - assertEquals(2, resultRequisition.getNodes().size()); - - RequisitionNode resultNode = resultRequisition.getNodes().get(0); - assertEquals("TestNode", resultNode.getNodeLabel()); - assertEquals("TestNode", resultNode.getForeignId()); - assertEquals("Test-Parent-Foreign-Source", resultNode.getParentForeignSource()); - assertEquals("Test-Parent-Foreign-Id", resultNode.getParentForeignId()); - assertEquals("Test-Parent-Node-Label", resultNode.getParentNodeLabel()); - assertEquals("Test-Location", resultNode.getLocation()); - - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.vendor.name).getValue(), "Vater"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.city.name).getValue(), "Braunschweig"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.vendorPhone.name).getValue(), "123"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.address1.name).getValue(), "Wilhelmstraße 30"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.description.name).getValue(), "POB: Johann Carl Friedrich Gauß"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.comment.name).getValue(), "Died in Göttingen"); - - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.latitude.name).getValue(), "54.9633229"); - assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.longitude.name).getValue(), "1"); - - RequisitionInterface resultInterface = RequisitionUtils.findInterface(resultNode, "1.2.3.4"); - assertEquals(PrimaryType.PRIMARY, resultInterface.getSnmpPrimary()); - assertEquals(1, resultInterface.getStatus()); - - RequisitionMonitoredService resultService = RequisitionUtils.findMonitoredService(resultInterface, "Test"); - assertEquals("Test", resultService.getServiceName()); - - RequisitionCategory findCategory = RequisitionUtils.findCategory(resultNode, "Test"); - assertEquals("Test", findCategory.getName()); - - assertThat(resultNode.getMetaDatas(), containsInAnyOrder( - new MetaData("requisition", "KeyWithoutContext", "Foo"), - new MetaData("Context", "KeyWithContext", "Bar"))); - } - - @Test - public void getNodeWithMultipleIpInterfaces() throws Exception { - Requisition resultRequisition = (Requisition) xlsSource.dump(); - assertEquals(resultRequisition.getForeignSource(), "test"); - RequisitionNode resultNode = resultRequisition.getNodes().get(1); - assertEquals(resultNode.getInterfaces().size(), 2); - assertEquals(resultNode.getNodeLabel(), "Node2Ips"); - assertEquals(resultNode.getInterfaces().get(0).getIpAddr(),"23.23.23.23"); - assertEquals(resultNode.getInterfaces().get(0).getSnmpPrimary(),"P"); - assertEquals(resultNode.getInterfaces().get(1).getIpAddr(),"42.42.42.42"); - assertEquals(resultNode.getInterfaces().get(1).getSnmpPrimary(),"S"); - } + private XlsSource xlsSource; + + @Test + public void testxlsSource() throws Exception { + System.out.println("**********testxlssource"); + MockInstanceConfiguration config = new MockInstanceConfiguration("test"); + config.set("encoding", "ISO-8859-1"); + config.set("file", Paths.get("src/test/resources/test.xls")); + + xlsSource = new XlsSource(config); + + publishTestRequisitionAndSheet("test"); + + basicTest("test"); + + System.out.println("********** end testxlssource"); + } + + @Test + public void testCsvSource() throws Exception { + System.out.println("**********testcsvsource"); + MockInstanceConfiguration config = new MockInstanceConfiguration("testcsv"); + config.set("encoding", "ISO-8859-1"); + config.set("file", Paths.get("src/test/resources/testcsv.csv")); + + xlsSource = new XlsSource(config); + + publishTestRequisitionAndSheet("testcsv"); + + basicTest("testcsv"); + + System.out.println("**********end testcsvsource"); + + } + + @Test + public void testCsvSourceNoHeader() throws Exception { + System.out.println("**********testcsvsource-noheader"); + MockInstanceConfiguration config = new MockInstanceConfiguration("testcsv-noheaders"); + config.set("encoding", "ISO-8859-1"); + config.set("file", Paths.get("src/test/resources/testcsv-noheaders.csv")); + + config.set("org.opennms.pris.spreadsheet.fields", + "Parent_Foreign_Source,Parent_Foreign_ID,Parent_Node_Label,ID_,Node_Label,Location,Asset_Description,IP_Address,MgmtType_For_SNMP,InterfaceStatus,Cat_Test,Svc_Test,Asset_City,Asset_Address1,Asset_Address2,Asset_Comment,Asset_Vendor,Asset_VendorPhone,MetaData_KeyWithoutContext,MetaData_Context:KeyWithContext,Asset_latitude,Asset_longitude"); + + xlsSource = new XlsSource(config); + + publishTestRequisitionAndSheet("testcsv-noheaders"); + + basicTest("testcsv-noheaders"); + + System.out.println("**********end testcsvsource-noheader"); + + } + + // test method used by xls and csv tests + public void basicTest(String foreignSource) throws Exception { + Requisition resultRequisition = (Requisition) xlsSource.dump(); + + assertEquals(resultRequisition.getForeignSource(), foreignSource); + assertEquals(2, resultRequisition.getNodes().size()); + + RequisitionNode resultNode = resultRequisition.getNodes().get(0); + assertEquals("TestNode", resultNode.getNodeLabel()); + assertEquals("TestNode", resultNode.getForeignId()); + assertEquals("Test-Parent-Foreign-Source", resultNode.getParentForeignSource()); + assertEquals("Test-Parent-Foreign-Id", resultNode.getParentForeignId()); + assertEquals("Test-Parent-Node-Label", resultNode.getParentNodeLabel()); + assertEquals("Test-Location", resultNode.getLocation()); + + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.vendor.name).getValue(), "Vater"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.city.name).getValue(), "Braunschweig"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.vendorPhone.name).getValue(), "123"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.address1.name).getValue(), "Wilhelmstraße 30"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.description.name).getValue(), + "POB: Johann Carl Friedrich Gauß"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.comment.name).getValue(), "Died in Göttingen"); + + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.latitude.name).getValue(), "54.9633229"); + assertEquals(RequisitionUtils.findAsset(resultNode, AssetField.longitude.name).getValue(), "1"); + + RequisitionInterface resultInterface = RequisitionUtils.findInterface(resultNode, "1.2.3.4"); + assertEquals(PrimaryType.PRIMARY, resultInterface.getSnmpPrimary()); + assertEquals(1, resultInterface.getStatus()); + + RequisitionMonitoredService resultService = RequisitionUtils.findMonitoredService(resultInterface, "Test"); + assertEquals("Test", resultService.getServiceName()); + + RequisitionCategory findCategory = RequisitionUtils.findCategory(resultNode, "Test"); + assertEquals("Test", findCategory.getName()); + + assertThat(resultNode.getMetaDatas(), + containsInAnyOrder(new MetaData("requisition", "KeyWithoutContext", "Foo"), + new MetaData("Context", "KeyWithContext", "Bar"))); + } + + // test method used by xls and csv tests + public void getNodeWithMultipleIpInterfaces(String foreignSource) throws Exception { + Requisition resultRequisition = (Requisition) xlsSource.dump(); + assertEquals(resultRequisition.getForeignSource(), foreignSource); + RequisitionNode resultNode = resultRequisition.getNodes().get(1); + assertEquals(resultNode.getInterfaces().size(), 2); + assertEquals(resultNode.getNodeLabel(), "Node2Ips"); + assertEquals(resultNode.getInterfaces().get(0).getIpAddr(), "23.23.23.23"); + assertEquals(resultNode.getInterfaces().get(0).getSnmpPrimary(), "P"); + assertEquals(resultNode.getInterfaces().get(1).getIpAddr(), "42.42.42.42"); + assertEquals(resultNode.getInterfaces().get(1).getSnmpPrimary(), "S"); + } + + public void publishTestRequisitionAndSheet(String name) { + + // print out parsed spreadsheet + File xls = new File(xlsSource.getXlsFile()); + Workbook workbook = xlsSource.getWorkbook(xls); + File xlsFile = new File("target/" + name + ".xls"); + xlsFile.delete(); + try (FileOutputStream outputStream = new FileOutputStream(xlsFile)) { + workbook.write(outputStream); + } catch (Exception ex) { + ex.printStackTrace(); + } + + // print out xml requisition + + File csvFile = new File("target/" + name + ".xml"); + csvFile.delete(); + try (FileOutputStream outputStream = new FileOutputStream(csvFile)) { + + Requisition resultRequisition = (Requisition) xlsSource.dump(); + + JAXBContext jc = JAXBContext.newInstance("org.opennms.pris.model"); + Marshaller marshaller = jc.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); + marshaller.marshal(resultRequisition, outputStream); + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv-noheaders.csv b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv-noheaders.csv new file mode 100644 index 00000000..00786468 --- /dev/null +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv-noheaders.csv @@ -0,0 +1,3 @@ +Test-Parent-Foreign-Source,Test-Parent-Foreign-Id,Test-Parent-Node-Label,TestNode,TestNode,Test-Location,POB: Johann Carl Friedrich Gauß,1.2.3.4,P,1,Test,Test,Braunschweig,Wilhelmstraße 30,,Died in Göttingen,Vater,123,Foo,Bar,54.9633229,1 +,,,,Node2Ips,Node2Ips-Location,,23.23.23.23,P,,,,,,,,,,,,, +,,,,Node2Ips,,,42.42.42.42,S,,,,,,,,,,,,, diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv.csv b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv.csv new file mode 100644 index 00000000..714217d7 --- /dev/null +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/resources/testcsv.csv @@ -0,0 +1,4 @@ +Parent_Foreign_Source,Parent_Foreign_ID,Parent_Node_Label,ID_,Node_Label,Location,Asset_Description,IP_Address,MgmtType_For_SNMP,InterfaceStatus,Cat_Test,Svc_Test,Asset_City,Asset_Address1,Asset_Address2,Asset_Comment,Asset_Vendor,Asset_VendorPhone,MetaData_KeyWithoutContext,MetaData_Context:KeyWithContext,Asset_latitude,Asset_longitude +Test-Parent-Foreign-Source,Test-Parent-Foreign-Id,Test-Parent-Node-Label,TestNode,TestNode,Test-Location,POB: Johann Carl Friedrich Gauß,1.2.3.4,P,1,Test,Test,Braunschweig,Wilhelmstraße 30,,Died in Göttingen,Vater,123,Foo,Bar,54.9633229,1 +,,,,Node2Ips,Node2Ips-Location,,23.23.23.23,P,,,,,,,,,,,,, +,,,,Node2Ips,,,42.42.42.42,S,,,,,,,,,,,,, diff --git a/pom.xml b/pom.xml index 16f523be..89003f14 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ 1.2.3 1.10 2.7 + 3.12.0 1.2.1 2.4.15 [30.0-jre,) From d771ad3fe6970b59aa3e227106a0edaace259973 Mon Sep 17 00:00:00 2001 From: gallenc Date: Tue, 23 May 2023 17:38:37 +0100 Subject: [PATCH 02/15] documentation and examples for csv file reader --- .../sources/examples/csv/global.properties | 8 ++ .../myinventory-noheaders.csv | 6 ++ .../requisition.properties | 12 +++ .../requisitions/myinventory/myinventory.csv | 7 ++ .../myinventory/requisition.properties | 10 ++ docs/modules/sources/nav.adoc | 1 + docs/modules/sources/pages/csv.adoc | 40 ++++++++ .../opennms-pris-plugins-xls/pom.xml | 95 +++++++++---------- .../pris/plugins/xls/source/XlsSource.java | 66 +++++-------- .../plugins/xls/source/XlsSourceTest.java | 9 +- 10 files changed, 155 insertions(+), 99 deletions(-) create mode 100644 docs/modules/sources/examples/csv/global.properties create mode 100644 docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/myinventory-noheaders.csv create mode 100644 docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/requisition.properties create mode 100644 docs/modules/sources/examples/csv/requisitions/myinventory/myinventory.csv create mode 100644 docs/modules/sources/examples/csv/requisitions/myinventory/requisition.properties create mode 100644 docs/modules/sources/pages/csv.adoc diff --git a/docs/modules/sources/examples/csv/global.properties b/docs/modules/sources/examples/csv/global.properties new file mode 100644 index 00000000..df2f6335 --- /dev/null +++ b/docs/modules/sources/examples/csv/global.properties @@ -0,0 +1,8 @@ +### File: global.properties +# Start web server +# The web server listens on all interfaces and can be accessed on TCP port 8000 +# URL: http://${your-ip}:8000/requisitions/${name-requisition-cfg} + +driver = http +host = 0.0.0.0 +port = 8000 diff --git a/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/myinventory-noheaders.csv b/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/myinventory-noheaders.csv new file mode 100644 index 00000000..45550ff3 --- /dev/null +++ b/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/myinventory-noheaders.csv @@ -0,0 +1,6 @@ +bbone-gw1,10.0.23.1,P,ICMP;SNMP,Backbone +bbone-gw2,10.0.23.2,P,ICMP;SNMP,Backbone +rt-01,172.16.23.1,P,ICMP;SNMP,Office +rt-02,172.16.23.2,P,ICMP;SNMP,Office +rt-02,172.16.23.3,S,ICMP;StrafePing, +rt-02,192.168.30.1,N,, diff --git a/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/requisition.properties b/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/requisition.properties new file mode 100644 index 00000000..e4867764 --- /dev/null +++ b/docs/modules/sources/examples/csv/requisitions/myinventory-noheaders/requisition.properties @@ -0,0 +1,12 @@ +### File: myRouter/requisition.properties +# This example imports devices from a spreadsheet +# named "myRouter" from the myInventory.xls file +# Path to the XLS fils is relative to +# requisitions.properties +source = xls +source.file = ./myinventory-noheaders.csv + +source.org.opennms.pris.spreadsheet.fields=Node_Label,IP_Management,MgmtType_,svc_Forced,cat_Environment + +### default no-operation mapper +mapper = echo diff --git a/docs/modules/sources/examples/csv/requisitions/myinventory/myinventory.csv b/docs/modules/sources/examples/csv/requisitions/myinventory/myinventory.csv new file mode 100644 index 00000000..6cefc502 --- /dev/null +++ b/docs/modules/sources/examples/csv/requisitions/myinventory/myinventory.csv @@ -0,0 +1,7 @@ +Node_Label,IP_Management,MgmtType_,svc_Forced,cat_Environment +bbone-gw1,10.0.23.1,P,ICMP;SNMP,Backbone +bbone-gw2,10.0.23.2,P,ICMP;SNMP,Backbone +rt-01,172.16.23.1,P,ICMP;SNMP,Office +rt-02,172.16.23.2,P,ICMP;SNMP,Office +rt-02,172.16.23.3,S,ICMP;StrafePing, +rt-02,192.168.30.1,N,, diff --git a/docs/modules/sources/examples/csv/requisitions/myinventory/requisition.properties b/docs/modules/sources/examples/csv/requisitions/myinventory/requisition.properties new file mode 100644 index 00000000..3df54bf3 --- /dev/null +++ b/docs/modules/sources/examples/csv/requisitions/myinventory/requisition.properties @@ -0,0 +1,10 @@ +### File: myRouter/requisition.properties +# This example imports devices from a spreadsheet +# named "myRouter" from the myInventory.xls file +# Path to the XLS fils is relative to +# requisitions.properties +source = xls +source.file = ./myinventory.csv + +### default no-operation mapper +mapper = echo diff --git a/docs/modules/sources/nav.adoc b/docs/modules/sources/nav.adoc index 9453139a..bbb1a389 100644 --- a/docs/modules/sources/nav.adoc +++ b/docs/modules/sources/nav.adoc @@ -7,3 +7,4 @@ * xref:ocs.adoc[] * xref:script.adoc[] * xref:xls.adoc[] +* xref:csv.adoc[] diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc new file mode 100644 index 00000000..73fad1b1 --- /dev/null +++ b/docs/modules/sources/pages/csv.adoc @@ -0,0 +1,40 @@ += CSV Source + +The `xls` source can also create a requisition from a UTF-8 encoded comma separated variable (CSV) file if the given file name has the `.csv` suffix. + +In this case the first line of the csv file should contain a comma separated list of headers in the same way the spreadsheet should be configured in a normal xls source. +Alternatively, a property can be set containing comma separated set of headers to be is used as the first line of the csv file. +This allows csv file to be raad which don't have a header line. + +[options="header",autowidth"] +|=== +| Parameter | Required | Description +| `source` | * | set `xls` to use the XLS source for this requisition +| `source.file` | * | path of the CSV file to read relative to the `requisition.properties`.Note the file name must end with `.csv` +| `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the csv file is used as the column headers in the same way as in the xls data source. +If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. +|=== + +The structure of the csv file should follow the same rules and use the same headers as in the xls data source. + +However, any columns which would contain comma separated values in a spreadsheet must have the contents delineated using a semicolon ';' character rather than commas. +In the following example, the svc_Forced services ICMP;SNMP are separated using a semicolon. + +``` +Node_Label,IP_Management,MgmtType_,svc_Forced,cat_Environment +bbone-gw2,10.0.23.2,P,ICMP;SNMP,Backbone +``` + +Example configuration for the requisition myinventory from a csv file myinventory.csv +[source,bash] +---- +include::example$csv/requisitions/myinventory/requisition.properties[] +---- + +Example configuration for the requisition myinventory-noheaders from a csv file myinventory-noheaders.csv +This has a source.org.opennms.pris.spreadsheet.fields property set. + +[source,bash] +---- +include::example$csv/requisitions/myinventory-noheaders/requisition.properties[] +---- diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml b/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml index 34ff8647..7031f74a 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/pom.xml @@ -1,56 +1,55 @@ - - 4.0.0 + + 4.0.0 - - org.opennms - opennms-pris-plugins - BLEEDING - + + org.opennms + opennms-pris-plugins + BLEEDING + - opennms-pris-plugins-xls - jar + opennms-pris-plugins-xls + jar - OpenNMS :: Provisioning Integration Server :: Plugins :: XLS + OpenNMS :: Provisioning Integration Server :: Plugins :: XLS - - 4.1.1 - + + 4.1.1 + - - - - org.apache.poi - poi - ${apachePoiVersion} - - - org.apache.poi - poi-ooxml - ${apachePoiVersion} - - - org.apache.commons - commons-lang3 - ${commonsLang3Version} - - - - ${project.groupId} - opennms-pris-api - tests - - + + + + org.apache.poi + poi + ${apachePoiVersion} + + + org.apache.poi + poi-ooxml + ${apachePoiVersion} + + + org.apache.commons + commons-lang3 + ${commonsLang3Version} + + + + ${project.groupId} + opennms-pris-api + tests + + - - - - - org.apache.maven.plugins - maven-shade-plugin - - - + + + + + org.apache.maven.plugins + maven-shade-plugin + + + diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java b/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java index 968d05a8..fd435e5a 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/main/java/org/opennms/opennms/pris/plugins/xls/source/XlsSource.java @@ -22,7 +22,8 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; @@ -42,7 +43,6 @@ import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -75,9 +75,10 @@ public class XlsSource implements Source { private final String WITHIN_SPLITTER = ","; - // note that the csv file is delimited by ',' but multiple services must be delimited by ';' in cells + // note that the csv file cells are delimited by ',' but multiple values (services) within a cell must be delimited by ';' within cells private final String CSV_FILE_DELIMITER = ","; private final String CSV_FILE_WITHIN_SPLITTER = ";"; + private final String SPREADSHEET_HEADER_FIELDS="org.opennms.pris.spreadsheet.fields"; private final String PREFIX_FOR_ASSETS = "Asset_"; private final String PREFIX_FOR_METADATA = "MetaData_"; @@ -137,15 +138,15 @@ public static Integer getIntValueFromCell(Cell cell) { public XlsSource(final InstanceConfiguration config) { this.config = config; - + this.encoding = config.getString("encoding", "ISO-8859-1"); - this.csvHeaders = config.getString("org.opennms.pris.spreadsheet.fields"); + this.csvHeaders = config.getString(SPREADSHEET_HEADER_FIELDS,""); } public Workbook getWorkbook(File file) { - // if file is csv file then create spreadsheet in workbook from lines in csv file. + // if file is csv file then create spreadsheet in workbook from lines in csv file. String fileName = file.getName(); String extension = null; int i = fileName.lastIndexOf('.'); @@ -155,14 +156,16 @@ public Workbook getWorkbook(File file) { } if ("csv".equals(extension)) { + FileInputStream fis=null; try { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(fileName); - // if headers provided as a property then create first row of spreadsheet with + // if headers provided as a configuration property then create first row of spreadsheet with // headers int rowNum = 0; - if (csvHeaders != null) { + if (csvHeaders != null && ! csvHeaders.isEmpty() ) { + LOGGER.info("csv headers property set "+SPREADSHEET_HEADER_FIELDS+ " = "+csvHeaders); String[] headers = csvHeaders.split(CSV_FILE_DELIMITER); HSSFRow firstRow = sheet.createRow(rowNum); @@ -175,7 +178,10 @@ public Workbook getWorkbook(File file) { // create rest of spreadsheet with csv data in file see // https://javacodepoint.com/java-code-convert-csv-to-excel-file-using-apache-poi/ - BufferedReader br = new BufferedReader(new FileReader(file)); + fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr); + String nextLine; while ((nextLine = br.readLine()) != null) { Row currentRow = sheet.createRow(rowNum); @@ -190,8 +196,6 @@ public Workbook getWorkbook(File file) { } else { // String values we always substitute SPLITTERS String stringCellData = rowData[column].trim().replace(CSV_FILE_WITHIN_SPLITTER, WITHIN_SPLITTER); - //TODO REMOVE - System.out.println("rowNum "+rowNum + " column "+column+ " "+stringCellData); Cell cell = currentRow.createCell(column); cell.setCellValue(stringCellData); } @@ -199,11 +203,19 @@ public Workbook getWorkbook(File file) { rowNum++; } + + br.close(); + return workbook; } catch (Exception ex) { LOGGER.error("can not create workbook from csv file {}", file.getAbsolutePath(), ex); return null; + } finally { + if(fis!=null) + try { + fis.close(); + } catch (IOException e) {} } } @@ -290,8 +302,6 @@ public Object dump() throws MissingRequiredColumnHeaderException, Exception { // adding parent data cell = getRelevantColumnID(row, OPTIONAL_UNIQUE_HEADERS.PREFIX_PARENT_FOREIGN_SOURCE); - //TODO REMOVE - System.out.println("xxx foreign source: "+OPTIONAL_UNIQUE_HEADERS.PREFIX_PARENT_FOREIGN_SOURCE+" "+ cell); if (cell != null) { node.setParentForeignSource(XlsSource.getStringValueFromCell(cell)); } @@ -331,17 +341,6 @@ private Cell getRelevantColumnID(Row row, REQUIRED_UNIQUE_PREFIXES prefix) { } private Cell getRelevantColumnID(Row row, OPTIONAL_UNIQUE_HEADERS header) { - //TODO REMOVE - System.out.println("header.HEADER:"+header.HEADER); - System.out.print("header.HEADER bytes:"); - byte[] a = header.HEADER.getBytes(); - for(int i=0; i< a.length ; i++) { - System.out.print(a[i] +" "); - } - System.out.println(); - for(Entry entry: optionalUniquHeaders.entrySet()) { - System.out.println(" optionalUniquHeaders:"+entry); - } Integer columnId = optionalUniquHeaders.get(header.HEADER); if (columnId == null) { return null; @@ -373,31 +372,12 @@ private Map initializeRequiredColumns(Sheet sheet) throws Missi private Map initializeOptionalUniquHeaders(Sheet sheet) { Map result = new HashMap<>(); - System.out.println("****************** Start initialise Unique headers"); for (OPTIONAL_UNIQUE_HEADERS header : OPTIONAL_UNIQUE_HEADERS.values()) { Row row = sheet.getRow(0); Iterator celliterator = row.cellIterator(); while (celliterator.hasNext()) { Cell cell = celliterator.next(); - //TODO remove - System.out.println("initialise Optional: "+cell.getStringCellValue()+" "+cell.getStringCellValue().toLowerCase()+" "+header.HEADER.toLowerCase()); - System.out.print("header.HEADER bytes: "); - byte[] a = header.HEADER.toLowerCase().getBytes(); - for(int i=0; i< a.length ; i++) { - System.out.print(a[i] +" "); - } - System.out.println(" header: "+ new String(a, StandardCharsets.UTF_8)); - System.out.print("cell value bytes: "); - byte[] b = cell.getStringCellValue().toLowerCase().getBytes(); - for(int i=0; i< b.length ; i++) { - System.out.print(b[i] +" "); - } - System.out.println(" cell: "+ new String(b, StandardCharsets.UTF_8)); - - - if (cell.getStringCellValue().toLowerCase().startsWith(header.HEADER.toLowerCase())) { - System.out.println("put header : "+header.HEADER+" cell index: "+cell.getColumnIndex() ); result.put(header.HEADER, cell.getColumnIndex()); } } diff --git a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java index f1926290..792d1d91 100644 --- a/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java +++ b/opennms-pris-plugins/opennms-pris-plugins-xls/src/test/java/org/opennms/opennms/pris/plugins/xls/source/XlsSourceTest.java @@ -33,7 +33,6 @@ public class XlsSourceTest { @Test public void testxlsSource() throws Exception { - System.out.println("**********testxlssource"); MockInstanceConfiguration config = new MockInstanceConfiguration("test"); config.set("encoding", "ISO-8859-1"); config.set("file", Paths.get("src/test/resources/test.xls")); @@ -44,12 +43,11 @@ public void testxlsSource() throws Exception { basicTest("test"); - System.out.println("********** end testxlssource"); } @Test public void testCsvSource() throws Exception { - System.out.println("**********testcsvsource"); + MockInstanceConfiguration config = new MockInstanceConfiguration("testcsv"); config.set("encoding", "ISO-8859-1"); config.set("file", Paths.get("src/test/resources/testcsv.csv")); @@ -60,13 +58,10 @@ public void testCsvSource() throws Exception { basicTest("testcsv"); - System.out.println("**********end testcsvsource"); - } @Test public void testCsvSourceNoHeader() throws Exception { - System.out.println("**********testcsvsource-noheader"); MockInstanceConfiguration config = new MockInstanceConfiguration("testcsv-noheaders"); config.set("encoding", "ISO-8859-1"); config.set("file", Paths.get("src/test/resources/testcsv-noheaders.csv")); @@ -80,8 +75,6 @@ public void testCsvSourceNoHeader() throws Exception { basicTest("testcsv-noheaders"); - System.out.println("**********end testcsvsource-noheader"); - } // test method used by xls and csv tests From 47bdcb7d85bbbcb027bd80b1e74194cfa1622273 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:12:57 +0100 Subject: [PATCH 03/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 73fad1b1..bea5fae5 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -1,6 +1,6 @@ = CSV Source -The `xls` source can also create a requisition from a UTF-8 encoded comma separated variable (CSV) file if the given file name has the `.csv` suffix. +The `xls` source can also create a requisition from a UTF-8 encoded, comma-separated variable (CSV) file if the given file name has the `.csv` suffix. In this case the first line of the csv file should contain a comma separated list of headers in the same way the spreadsheet should be configured in a normal xls source. Alternatively, a property can be set containing comma separated set of headers to be is used as the first line of the csv file. From 0879cca9610c87a2853dcee7f5c0da02577bcdc6 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:13:06 +0100 Subject: [PATCH 04/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index bea5fae5..49e93b77 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -2,7 +2,7 @@ The `xls` source can also create a requisition from a UTF-8 encoded, comma-separated variable (CSV) file if the given file name has the `.csv` suffix. -In this case the first line of the csv file should contain a comma separated list of headers in the same way the spreadsheet should be configured in a normal xls source. +In this case the first line of the CSV file should contain a comma-separated list of headers in the same way the spreadsheet should be configured in a normal XLS source. Alternatively, a property can be set containing comma separated set of headers to be is used as the first line of the csv file. This allows csv file to be raad which don't have a header line. From 38222ffb967638111b58f8d6db140fe2639e6b68 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:13:15 +0100 Subject: [PATCH 05/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 49e93b77..444a3a5d 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -3,7 +3,7 @@ The `xls` source can also create a requisition from a UTF-8 encoded, comma-separated variable (CSV) file if the given file name has the `.csv` suffix. In this case the first line of the CSV file should contain a comma-separated list of headers in the same way the spreadsheet should be configured in a normal XLS source. -Alternatively, a property can be set containing comma separated set of headers to be is used as the first line of the csv file. +Alternatively, you can set a property containing a comma-separated set of headers to use as the first line of the CSV file. This allows csv file to be raad which don't have a header line. [options="header",autowidth"] From 6bb7fe8b742e097c5791a928579f6aee0f9783aa Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:13:22 +0100 Subject: [PATCH 06/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 444a3a5d..08d70e8d 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -4,7 +4,7 @@ The `xls` source can also create a requisition from a UTF-8 encoded, comma-separ In this case the first line of the CSV file should contain a comma-separated list of headers in the same way the spreadsheet should be configured in a normal XLS source. Alternatively, you can set a property containing a comma-separated set of headers to use as the first line of the CSV file. -This allows csv file to be raad which don't have a header line. +This lets {page-component-title} read CSV files that do not have a header. [options="header",autowidth"] |=== From 1e8758a6943d864b5a39bc718a5c918e1f40e3f2 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:13:39 +0100 Subject: [PATCH 07/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 08d70e8d..47bdefb2 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -15,7 +15,7 @@ This lets {page-component-title} read CSV files that do not have a header. If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. |=== -The structure of the csv file should follow the same rules and use the same headers as in the xls data source. +The structure of the CSV file should follow the same rules and use the same headers as in the XLS data source. However, any columns which would contain comma separated values in a spreadsheet must have the contents delineated using a semicolon ';' character rather than commas. In the following example, the svc_Forced services ICMP;SNMP are separated using a semicolon. From 394798afc7adeaa332e45a3956690084f33d4691 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:13:50 +0100 Subject: [PATCH 08/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 47bdefb2..489488dc 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -9,7 +9,7 @@ This lets {page-component-title} read CSV files that do not have a header. [options="header",autowidth"] |=== | Parameter | Required | Description -| `source` | * | set `xls` to use the XLS source for this requisition +| `source` | * | Set `xls` to use the XLS source for this requisition. | `source.file` | * | path of the CSV file to read relative to the `requisition.properties`.Note the file name must end with `.csv` | `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the csv file is used as the column headers in the same way as in the xls data source. If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. From b3a7f14fafdc41476cb11dad45cf5c3def95acd0 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:14:00 +0100 Subject: [PATCH 09/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 489488dc..c7fc1511 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -17,7 +17,7 @@ If this property is set, value of this field should be a comma separated set of The structure of the CSV file should follow the same rules and use the same headers as in the XLS data source. -However, any columns which would contain comma separated values in a spreadsheet must have the contents delineated using a semicolon ';' character rather than commas. +However, any columns that would contain comma-separated values in a spreadsheet must have the contents delineated using a semicolon ';' character rather than commas. In the following example, the svc_Forced services ICMP;SNMP are separated using a semicolon. ``` From a0ea0c63edf68919f381d4e41cb1db60ebae2861 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:14:10 +0100 Subject: [PATCH 10/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index c7fc1511..6df8814c 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -25,7 +25,7 @@ Node_Label,IP_Management,MgmtType_,svc_Forced,cat_Environment bbone-gw2,10.0.23.2,P,ICMP;SNMP,Backbone ``` -Example configuration for the requisition myinventory from a csv file myinventory.csv +Example configuration for the requisition `myinventory` from a CSV file `myinventory.csv`: [source,bash] ---- include::example$csv/requisitions/myinventory/requisition.properties[] From 5e079650f8465fd576cbe14dc02ad396a9d012bb Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:14:19 +0100 Subject: [PATCH 11/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 6df8814c..d7772975 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -31,7 +31,7 @@ Example configuration for the requisition `myinventory` from a CSV file `myinven include::example$csv/requisitions/myinventory/requisition.properties[] ---- -Example configuration for the requisition myinventory-noheaders from a csv file myinventory-noheaders.csv +Example configuration for the requisition `myinventory-noheaders` from a CSV file `myinventory-noheaders.csv`: This has a source.org.opennms.pris.spreadsheet.fields property set. [source,bash] From 1535c7382647aa4ba9971f00211567837153cb07 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:14:31 +0100 Subject: [PATCH 12/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index d7772975..5f425749 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -32,7 +32,7 @@ include::example$csv/requisitions/myinventory/requisition.properties[] ---- Example configuration for the requisition `myinventory-noheaders` from a CSV file `myinventory-noheaders.csv`: -This has a source.org.opennms.pris.spreadsheet.fields property set. +This example has a `source.org.opennms.pris.spreadsheet.fields` property set: [source,bash] ---- From 15424771486aa005b673e9e0a239d14eb3d11b3d Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:14:53 +0100 Subject: [PATCH 13/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 5f425749..58296e67 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -10,7 +10,8 @@ This lets {page-component-title} read CSV files that do not have a header. |=== | Parameter | Required | Description | `source` | * | Set `xls` to use the XLS source for this requisition. -| `source.file` | * | path of the CSV file to read relative to the `requisition.properties`.Note the file name must end with `.csv` +| `source.file` | * | Path of the CSV file to read relative to the `requisition.properties`. +Note that the file name must end with `.csv`. | `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the csv file is used as the column headers in the same way as in the xls data source. If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. |=== From aa8b19cb8c05ed05845aa904a896b45800140c52 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:15:08 +0100 Subject: [PATCH 14/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index 58296e67..c890b975 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -12,7 +12,7 @@ This lets {page-component-title} read CSV files that do not have a header. | `source` | * | Set `xls` to use the XLS source for this requisition. | `source.file` | * | Path of the CSV file to read relative to the `requisition.properties`. Note that the file name must end with `.csv`. -| `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the csv file is used as the column headers in the same way as in the xls data source. +| `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the CSV file is used as the column headers in the same way as in the XLS data source. If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. |=== From 282f4efea560a338d449007f319dc43a0cf131e5 Mon Sep 17 00:00:00 2001 From: Craig Gallen Date: Thu, 8 Jun 2023 09:15:52 +0100 Subject: [PATCH 15/15] Update docs/modules/sources/pages/csv.adoc Co-authored-by: Bonrob2 <59453630+Bonrob2@users.noreply.github.com> --- docs/modules/sources/pages/csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sources/pages/csv.adoc b/docs/modules/sources/pages/csv.adoc index c890b975..cd03ac82 100644 --- a/docs/modules/sources/pages/csv.adoc +++ b/docs/modules/sources/pages/csv.adoc @@ -13,7 +13,7 @@ This lets {page-component-title} read CSV files that do not have a header. | `source.file` | * | Path of the CSV file to read relative to the `requisition.properties`. Note that the file name must end with `.csv`. | `source.org.opennms.pris.spreadsheet.fields` | | If this property is not present, the first line of the CSV file is used as the column headers in the same way as in the XLS data source. -If this property is set, value of this field should be a comma separated set of headers to be used instead of using the first line of the csv file. +If this property is set, the value of this field should be a comma-separated set of headers to use instead of using the first line of the CSV file. |=== The structure of the CSV file should follow the same rules and use the same headers as in the XLS data source.