You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2013/07/22 10:10:26 UTC
[13/64] [partial] Hard rename of all 'org/eobjects' folders to
'org/apache'.
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java b/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java
new file mode 100644
index 0000000..b43c5d6
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java
@@ -0,0 +1,341 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.eobjects.metamodel.excel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.ss.usermodel.BuiltinFormats;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.FontUnderline;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.model.SharedStringsTable;
+import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.eobjects.metamodel.data.Style;
+import org.eobjects.metamodel.data.Style.SizeUnit;
+import org.eobjects.metamodel.data.StyleBuilder;
+import org.eobjects.metamodel.util.DateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * XML handler for transforming a sheet into rows. Uses an
+ * {@link XlsxRowCallback} to publish identified rows.
+ *
+ * @author Kasper Sørensen
+ */
+final class XlsxSheetToRowsHandler extends DefaultHandler {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(XlsxSheetToRowsHandler.class);
+
+ private static enum XssfDataType {
+ BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,
+ }
+
+ // global variables
+ private final XlsxRowCallback _callback;
+ private final ExcelConfiguration _configuration;
+ private final StylesTable _stylesTable;
+ private final SharedStringsTable _sharedStringTable;
+
+ // variables used to hold information about the current rows
+ private int _rowNumber;
+ private final List<String> _rowValues;
+ private final List<Style> _styles;
+
+ // variables used to hold information about the current visited cells
+ private final StringBuilder _value;
+ private final StyleBuilder _style;
+ private boolean _inCell;
+ private boolean _inFormula;
+ private int _columnNumber;
+ private XssfDataType _dataType;
+ private int _formatIndex;
+ private String _formatString;
+
+ public XlsxSheetToRowsHandler(XlsxRowCallback callback,
+ XSSFReader xssfReader, ExcelConfiguration configuration)
+ throws Exception {
+ _callback = callback;
+ _configuration = configuration;
+
+ _sharedStringTable = xssfReader.getSharedStringsTable();
+ _stylesTable = xssfReader.getStylesTable();
+
+ _value = new StringBuilder();
+ _style = new StyleBuilder();
+ _rowValues = new ArrayList<String>();
+ _styles = new ArrayList<Style>();
+ _rowNumber = -1;
+ _inCell = false;
+ _inFormula = false;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if ("row".equals(qName)) {
+ // element is a row
+
+ // excel row numbers are 1-based
+ int rowNumber = Integer.parseInt(attributes.getValue("r"));
+ rowNumber = rowNumber - 1;
+
+ if (_configuration.isSkipEmptyLines()) {
+ _rowNumber++;
+ } else {
+ while (_rowNumber + 1 < rowNumber) {
+ // empty lines are not skipped, so dispatch empty lines
+ _rowNumber++;
+ List<String> emptyValues = Collections.emptyList();
+ List<Style> emptyStyles = Collections.emptyList();
+ _callback.row(_rowNumber, emptyValues, emptyStyles);
+ }
+ _rowNumber = rowNumber;
+ }
+ } else if ("c".equals(qName)) {
+ // element is a cell
+
+ _inCell = true;
+
+ final String r = attributes.getValue("r");
+ int firstDigit = -1;
+ for (int c = 0; c < r.length(); ++c) {
+ if (Character.isDigit(r.charAt(c))) {
+ firstDigit = c;
+ break;
+ }
+ }
+ _columnNumber = nameToColumn(r.substring(0, firstDigit));
+
+ // Set up defaults.
+ _dataType = XssfDataType.NUMBER;
+ _formatIndex = -1;
+ _formatString = null;
+
+ final String cellType = attributes.getValue("t");
+ if ("b".equals(cellType)) {
+ _dataType = XssfDataType.BOOL;
+ } else if ("e".equals(cellType)) {
+ _dataType = XssfDataType.ERROR;
+ } else if ("inlineStr".equals(cellType)) {
+ _dataType = XssfDataType.INLINESTR;
+ } else if ("s".equals(cellType)) {
+ _dataType = XssfDataType.SSTINDEX;
+ } else if ("str".equals(cellType)) {
+ _dataType = XssfDataType.FORMULA;
+ }
+
+ String cellStyleStr = attributes.getValue("s");
+ if (cellStyleStr != null) {
+ // It's a number, but almost certainly one
+ // with a special style or format
+ int styleIndex = Integer.parseInt(cellStyleStr);
+ XSSFCellStyle style = _stylesTable.getStyleAt(styleIndex);
+
+ configureStyle(style);
+
+ if (_dataType == XssfDataType.NUMBER) {
+ this._formatIndex = style.getDataFormat();
+ this._formatString = style.getDataFormatString();
+ if (this._formatString == null) {
+ this._formatString = BuiltinFormats
+ .getBuiltinFormat(this._formatIndex);
+ }
+ }
+ }
+ } else if (_inCell && "f".equals(qName)) {
+ // skip the actual formula line
+ _inFormula = true;
+ }
+ }
+
+ private void configureStyle(XSSFCellStyle style) {
+ XSSFFont font = style.getFont();
+ if (font.getBold()) {
+ _style.bold();
+ }
+ if (font.getItalic()) {
+ _style.italic();
+ }
+ if (font.getUnderline() != FontUnderline.NONE.getByteValue()) {
+ _style.underline();
+ }
+
+ if (style.getFillPatternEnum() == FillPatternType.SOLID_FOREGROUND) {
+ XSSFColor fillForegroundXSSFColor = style
+ .getFillForegroundXSSFColor();
+ String argb = fillForegroundXSSFColor.getARGBHex();
+ if (argb != null) {
+ _style.background(argb.substring(2));
+ }
+ }
+
+ final XSSFFont stdFont = _stylesTable.getStyleAt(0).getFont();
+ final short fontHeight = style.getFont().getFontHeightInPoints();
+ if (stdFont.getFontHeightInPoints() != fontHeight) {
+ _style.fontSize(fontHeight, SizeUnit.PT);
+ }
+
+ XSSFColor fontColor = style.getFont().getXSSFColor();
+ if (fontColor != null) {
+ String argbHex = fontColor.getARGBHex();
+ if (argbHex != null) {
+ _style.foreground(argbHex.substring(2));
+ }
+ }
+
+ switch (style.getAlignmentEnum()) {
+ case LEFT:
+ _style.leftAligned();
+ break;
+ case RIGHT:
+ _style.rightAligned();
+ break;
+ case CENTER:
+ _style.centerAligned();
+ break;
+ case JUSTIFY:
+ _style.justifyAligned();
+ break;
+ }
+
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ if ("row".equals(qName)) {
+ // element was a row
+ boolean next = _callback.row(_rowNumber, _rowValues, _styles);
+ if (!next) {
+ throw new XlsxStopParsingException();
+ }
+ _rowValues.clear();
+ _styles.clear();
+ } else if ("c".equals(qName)) {
+ // element was a cell
+
+ _inCell = false;
+
+ while (_rowValues.size() < _columnNumber) {
+ _rowValues.add(null);
+ _styles.add(Style.NO_STYLE);
+ }
+
+ _rowValues.add(createValue());
+ _styles.add(_style.create());
+ _value.setLength(0);
+ _style.reset();
+ } else if (_inFormula && "f".equals(qName)) {
+ // skip the actual formula line
+ _inFormula = false;
+ }
+ }
+
+ private String createValue() {
+ if (_value.length() == 0) {
+ return null;
+ }
+
+ switch (_dataType) {
+
+ case BOOL:
+ char first = _value.charAt(0);
+ return first == '0' ? "false" : "true";
+ case ERROR:
+ logger.warn("Error-cell occurred: {}", _value);
+ return _value.toString();
+ case FORMULA:
+ return _value.toString();
+ case INLINESTR:
+ XSSFRichTextString rtsi = new XSSFRichTextString(_value.toString());
+ return rtsi.toString();
+ case SSTINDEX:
+ String sstIndex = _value.toString();
+ int idx = Integer.parseInt(sstIndex);
+ XSSFRichTextString rtss = new XSSFRichTextString(
+ _sharedStringTable.getEntryAt(idx));
+ return rtss.toString();
+ case NUMBER:
+ final String numberString = _value.toString();
+ if (_formatString != null) {
+ DataFormatter formatter = getDataFormatter();
+ if (HSSFDateUtil.isADateFormat(_formatIndex, _formatString)) {
+ Date date = DateUtil.getJavaDate(Double
+ .parseDouble(numberString));
+ return DateUtils.createDateFormat().format(date);
+ }
+ return formatter.formatRawCellContents(
+ Double.parseDouble(numberString), _formatIndex,
+ _formatString);
+ } else {
+ if (numberString.endsWith(".0")) {
+ // xlsx only stores doubles, so integers get ".0" appended
+ // to them
+ return numberString.substring(0, numberString.length() - 2);
+ }
+ return numberString;
+ }
+ default:
+ logger.error("Unsupported data type: {}", _dataType);
+ return "";
+ }
+ }
+
+ private DataFormatter getDataFormatter() {
+ return new DataFormatter();
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ if (_inCell && !_inFormula) {
+ _value.append(ch, start, length);
+ }
+ }
+
+ /**
+ * Converts an Excel column name like "C" to a zero-based index.
+ *
+ * @param name
+ * @return Index corresponding to the specified name
+ */
+ private int nameToColumn(String name) {
+ int column = -1;
+ for (int i = 0; i < name.length(); ++i) {
+ int c = name.charAt(i);
+ column = (column + 1) * 26 + c - 'A';
+ }
+ return column;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/XlsxSpreadsheetReaderDelegate.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/XlsxSpreadsheetReaderDelegate.java b/excel/src/main/java/org/apache/metamodel/excel/XlsxSpreadsheetReaderDelegate.java
new file mode 100644
index 0000000..dadd978
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/XlsxSpreadsheetReaderDelegate.java
@@ -0,0 +1,192 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.eobjects.metamodel.excel;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.RowPublisherDataSet;
+import org.eobjects.metamodel.data.Style;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.MutableSchema;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.AlphabeticSequence;
+import org.eobjects.metamodel.util.FileHelper;
+import org.eobjects.metamodel.util.Ref;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * {@link SpreadsheetReaderDelegate} implementation for the "new" XLSX format.
+ * This implementation is very efficient as it uses SAX XML parsing which does
+ * not bloat memory usage in the same way that POI's user model does.
+ *
+ * @author Kasper Sørensen
+ */
+final class XlsxSpreadsheetReaderDelegate implements SpreadsheetReaderDelegate {
+
+ private static final Logger logger = LoggerFactory.getLogger(XlsxSpreadsheetReaderDelegate.class);
+
+ private final ExcelConfiguration _configuration;
+ private final Map<String, String> _tableNamesToInternalIds;
+
+ public XlsxSpreadsheetReaderDelegate(ExcelConfiguration configuration) {
+ _configuration = configuration;
+ _tableNamesToInternalIds = new HashMap<String, String>();
+ }
+
+ @Override
+ public DataSet executeQuery(InputStream inputStream, Table table, Column[] columns, int maxRows) throws Exception {
+ final OPCPackage pkg = OPCPackage.open(inputStream);
+ final XSSFReader xssfReader = new XSSFReader(pkg);
+ final String relationshipId = _tableNamesToInternalIds.get(table.getName());
+
+ return buildDataSet(columns, maxRows, relationshipId, xssfReader);
+ }
+
+ @Override
+ public Schema createSchema(InputStream inputStream, String schemaName) throws Exception {
+ final MutableSchema schema = new MutableSchema(schemaName);
+ final OPCPackage pkg = OPCPackage.open(inputStream);
+ final XSSFReader xssfReader = new XSSFReader(pkg);
+
+ final XlsxWorkbookToTablesHandler workbookToTables = new XlsxWorkbookToTablesHandler(schema,
+ _tableNamesToInternalIds);
+ buildTables(xssfReader, workbookToTables);
+
+ for (Entry<String, String> entry : _tableNamesToInternalIds.entrySet()) {
+
+ final String tableName = entry.getKey();
+ final String relationshipId = entry.getValue();
+
+ final MutableTable table = (MutableTable) schema.getTableByName(tableName);
+
+ buildColumns(table, relationshipId, xssfReader);
+ }
+ return schema;
+ }
+
+ @Override
+ public void notifyTablesModified(Ref<InputStream> inputStreamRef) {
+ InputStream inputStream = inputStreamRef.get();
+ final XlsxWorkbookToTablesHandler workbookToTables = new XlsxWorkbookToTablesHandler(null,
+ _tableNamesToInternalIds);
+ try {
+ final OPCPackage pkg = OPCPackage.open(inputStream);
+ final XSSFReader xssfReader = new XSSFReader(pkg);
+ buildTables(xssfReader, workbookToTables);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ FileHelper.safeClose(inputStream);
+ }
+ }
+
+ private DataSet buildDataSet(final Column[] columns, int maxRows, final String relationshipId,
+ final XSSFReader xssfReader) throws Exception {
+
+ List<SelectItem> selectItems = new ArrayList<SelectItem>(columns.length);
+ for (Column column : columns) {
+ selectItems.add(new SelectItem(column));
+ }
+ final XlsxRowPublisherAction publishAction = new XlsxRowPublisherAction(_configuration, columns,
+ relationshipId, xssfReader);
+
+ return new RowPublisherDataSet(selectItems.toArray(new SelectItem[selectItems.size()]), maxRows, publishAction);
+ }
+
+ private void buildColumns(final MutableTable table, final String relationshipId, final XSSFReader xssfReader)
+ throws Exception {
+ final InputStream sheetData = xssfReader.getSheet(relationshipId);
+
+ final XlsxRowCallback rowCallback = new XlsxRowCallback() {
+ @Override
+ public boolean row(int rowNumber, List<String> values, List<Style> styles) {
+ final int columnNameLineNumber = _configuration.getColumnNameLineNumber();
+ if (columnNameLineNumber == ExcelConfiguration.NO_COLUMN_NAME_LINE) {
+ AlphabeticSequence alphabeticSequence = new AlphabeticSequence();
+ List<String> generatedColumnNames = new ArrayList<String>(values.size());
+ for (String originalColumnName : values) {
+ String columnName = alphabeticSequence.next();
+ if (originalColumnName == null) {
+ columnName = null;
+ }
+ generatedColumnNames.add(columnName);
+ }
+ buildColumns(table, generatedColumnNames);
+ return false;
+ } else {
+ final int zeroBasedLineNumber = columnNameLineNumber - 1;
+ if (rowNumber >= zeroBasedLineNumber) {
+ buildColumns(table, values);
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+ final XlsxSheetToRowsHandler handler = new XlsxSheetToRowsHandler(rowCallback, xssfReader, _configuration);
+
+ final XMLReader sheetParser = ExcelUtils.createXmlReader();
+ sheetParser.setContentHandler(handler);
+ try {
+ sheetParser.parse(new InputSource(sheetData));
+ } catch (XlsxStopParsingException e) {
+ logger.debug("Parsing stop signal thrown");
+ } finally {
+ FileHelper.safeClose(sheetData);
+ }
+ }
+
+ protected void buildColumns(final MutableTable table, final List<String> columnNames) {
+ int columnNumber = 0;
+ for (String columnName : columnNames) {
+ if (columnName != null || !_configuration.isSkipEmptyColumns()) {
+ if (columnName == null) {
+ columnName = "[Column " + (columnNumber + 1) + "]";
+ }
+ table.addColumn(new MutableColumn(columnName, ColumnType.VARCHAR, table, columnNumber, true));
+ }
+ columnNumber++;
+ }
+ }
+
+ private void buildTables(final XSSFReader xssfReader, final XlsxWorkbookToTablesHandler workbookToTables)
+ throws Exception {
+ final InputStream workbookData = xssfReader.getWorkbookData();
+ final XMLReader workbookParser = ExcelUtils.createXmlReader();
+ workbookParser.setContentHandler(workbookToTables);
+ workbookParser.parse(new InputSource(workbookData));
+ FileHelper.safeClose(workbookData);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/XlsxStopParsingException.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/XlsxStopParsingException.java b/excel/src/main/java/org/apache/metamodel/excel/XlsxStopParsingException.java
new file mode 100644
index 0000000..47d8078
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/XlsxStopParsingException.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.eobjects.metamodel.excel;
+
+import org.xml.sax.SAXException;
+
+/**
+ * Exception thrown when all elements of interest in a spreadsheet have been
+ * parsed.
+ *
+ * @author Kasper Sørensen
+ */
+final class XlsxStopParsingException extends SAXException {
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/XlsxWorkbookToTablesHandler.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/XlsxWorkbookToTablesHandler.java b/excel/src/main/java/org/apache/metamodel/excel/XlsxWorkbookToTablesHandler.java
new file mode 100644
index 0000000..fa65bf8
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/XlsxWorkbookToTablesHandler.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.eobjects.metamodel.excel;
+
+import java.util.Map;
+
+import org.eobjects.metamodel.schema.MutableSchema;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.schema.TableType;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * XML handler for transforming a workbook document into {@link Table}s in a
+ * MetaModel {@link Schema}.
+ *
+ * @author Kasper Sørensen
+ */
+final class XlsxWorkbookToTablesHandler extends DefaultHandler {
+
+ private final MutableSchema _schema;
+ private final Map<String, String> _tableNamesToRelationshipIds;
+
+ public XlsxWorkbookToTablesHandler(MutableSchema schema,
+ Map<String, String> tableNamesToRelationshipIds) {
+ _schema = schema;
+ _tableNamesToRelationshipIds = tableNamesToRelationshipIds;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if ("sheet".equals(qName)) {
+ String name = attributes.getValue("name");
+ assert name != null;
+ String relationId = attributes.getValue("r:id");
+ assert relationId != null;
+
+ if (_schema != null) {
+ MutableTable table = new MutableTable(name, TableType.TABLE,
+ _schema);
+ _schema.addTable(table);
+ }
+ _tableNamesToRelationshipIds.put(name, relationId);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/ZeroBasedRowIterator.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/ZeroBasedRowIterator.java b/excel/src/main/java/org/apache/metamodel/excel/ZeroBasedRowIterator.java
new file mode 100644
index 0000000..d897ec4
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/ZeroBasedRowIterator.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.eobjects.metamodel.excel;
+
+import java.util.Iterator;
+
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+
+/**
+ * An iterator implementation that iterates from the first logical (as opposed
+ * to physical, which is the default in POI) row in a spreadsheet.
+ *
+ * @author Kasper Sørensen
+ */
+final class ZeroBasedRowIterator implements Iterator<Row> {
+
+ private final Sheet _sheet;
+ private volatile int _rowNumber;
+
+ public ZeroBasedRowIterator(Sheet sheet) {
+ _sheet = sheet;
+ _rowNumber = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return _rowNumber < _sheet.getLastRowNum();
+ }
+
+ @Override
+ public Row next() {
+ _rowNumber++;
+ return _sheet.getRow(_rowNumber);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("remove() is not supported");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/apache/metamodel/excel/package-info.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/apache/metamodel/excel/package-info.java b/excel/src/main/java/org/apache/metamodel/excel/package-info.java
new file mode 100644
index 0000000..9bf3d30
--- /dev/null
+++ b/excel/src/main/java/org/apache/metamodel/excel/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+/**
+ * Module package for MS Excel spreadsheet files
+ */
+package org.eobjects.metamodel.excel;
+
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/DefaultSpreadsheetReaderDelegate.java b/excel/src/main/java/org/eobjects/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
deleted file mode 100644
index dc4a331..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import java.io.InputStream;
-import java.util.Iterator;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.data.EmptyDataSet;
-import org.eobjects.metamodel.data.MaxRowsDataSet;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.ColumnType;
-import org.eobjects.metamodel.schema.MutableColumn;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.MutableTable;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.util.AlphabeticSequence;
-import org.eobjects.metamodel.util.Ref;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The default {@link SpreadsheetReaderDelegate}, which uses POI's main user
- * model to read spreadsheets: the Workbook class.
- *
- * @author Kasper Sørensen
- */
-final class DefaultSpreadsheetReaderDelegate implements SpreadsheetReaderDelegate {
-
- private static final Logger logger = LoggerFactory.getLogger(DefaultSpreadsheetReaderDelegate.class);
-
- private final ExcelConfiguration _configuration;
-
- public DefaultSpreadsheetReaderDelegate(ExcelConfiguration configuration) {
- _configuration = configuration;
- }
-
- @Override
- public Schema createSchema(InputStream inputStream, String schemaName) {
- final MutableSchema schema = new MutableSchema(schemaName);
- final Workbook wb = ExcelUtils.readWorkbook(inputStream);
-
- for (int i = 0; i < wb.getNumberOfSheets(); i++) {
- final Sheet currentSheet = wb.getSheetAt(i);
- final MutableTable table = createTable(wb, currentSheet);
- table.setSchema(schema);
- schema.addTable(table);
- }
-
- return schema;
- }
-
- @Override
- public DataSet executeQuery(InputStream inputStream, Table table, Column[] columns, int maxRows) {
- final Workbook wb = ExcelUtils.readWorkbook(inputStream);
- final Sheet sheet = wb.getSheet(table.getName());
-
- if (sheet == null || sheet.getPhysicalNumberOfRows() == 0) {
- return new EmptyDataSet(columns);
- }
-
- DataSet dataSet = ExcelUtils.getDataSet(wb, sheet, table, _configuration);
-
- if (maxRows > 0) {
- dataSet = new MaxRowsDataSet(dataSet, maxRows);
- }
- return dataSet;
- }
-
- @Override
- public void notifyTablesModified(Ref<InputStream> inputStreamRef) {
- // do nothing
- }
-
- private MutableTable createTable(final Workbook wb, final Sheet sheet) {
- final MutableTable table = new MutableTable(sheet.getSheetName());
-
- if (sheet.getPhysicalNumberOfRows() <= 0) {
- // no physical rows in sheet
- return table;
- }
-
- final Iterator<Row> rowIterator = ExcelUtils.getRowIterator(sheet, _configuration, false);
-
- if (!rowIterator.hasNext()) {
- // no physical rows in sheet
- return table;
- }
-
-
- Row row = null;
-
- if (_configuration.isSkipEmptyLines()) {
- while (row == null && rowIterator.hasNext()) {
- row = rowIterator.next();
- }
- } else {
- row = rowIterator.next();
- }
-
- final int columnNameLineNumber = _configuration.getColumnNameLineNumber();
- if (columnNameLineNumber == ExcelConfiguration.NO_COLUMN_NAME_LINE) {
-
- // get to the first non-empty line (no matter if lines are skipped
- // or not we need to read ahead to figure out how many columns there
- // are!)
- while (row == null && rowIterator.hasNext()) {
- row = rowIterator.next();
- }
-
- // build columns by using alphabetic sequences
- // (A,B,C...)
- AlphabeticSequence sequence = new AlphabeticSequence();
-
- final int offset = getColumnOffset(row);
- for (int i = 0; i < offset; i++) {
- sequence.next();
- }
-
- for (int j = offset; j < row.getLastCellNum(); j++) {
- Column column = new MutableColumn(sequence.next(), ColumnType.VARCHAR, table, j, true);
- table.addColumn(column);
- }
- } else {
-
- boolean hasColumns = true;
-
- // iterate to the column name line number (if above 1)
- for (int j = 1; j < columnNameLineNumber; j++) {
- if (rowIterator.hasNext()) {
- row = rowIterator.next();
- } else {
- hasColumns = false;
- break;
- }
- }
-
- if (hasColumns) {
- createColumns(table, wb, row);
- }
- }
-
- return table;
- }
-
- /**
- * Builds columns based on row/cell values.
- *
- * @param table
- * @param wb
- * @param row
- */
- private void createColumns(MutableTable table, Workbook wb, Row row) {
- if (row == null) {
- logger.warn("Cannot create columns based on null row!");
- return;
- }
- final short rowLength = row.getLastCellNum();
-
- final int offset = getColumnOffset(row);
-
- // build columns based on cell values.
- for (int j = offset; j < rowLength; j++) {
- Cell cell = row.getCell(j);
- String columnName = ExcelUtils.getCellValue(wb, cell);
- if (columnName == null || "".equals(columnName)) {
- columnName = "[Column " + (j + 1) + "]";
- }
- Column column = new MutableColumn(columnName, ColumnType.VARCHAR, table, j, true);
- table.addColumn(column);
- }
- }
-
- /**
- * Gets the column offset (first column to include). This is dependent on
- * the row used for column processing and whether the skip empty columns
- * property is set.
- *
- * @param row
- * @return
- */
- private int getColumnOffset(Row row) {
- final int offset;
- if (_configuration.isSkipEmptyColumns()) {
- offset = row.getFirstCellNum();
- } else {
- offset = 0;
- }
- return offset;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelConfiguration.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelConfiguration.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelConfiguration.java
deleted file mode 100644
index 6ea490c..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelConfiguration.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import java.io.Serializable;
-import java.util.List;
-
-import org.eobjects.metamodel.util.BaseObject;
-
-/**
- * Represents the configuration for reading/parsing Excel spreadsheets.
- *
- * @see ExcelDataContext
- *
- * @author Kasper Sørensen
- */
-public final class ExcelConfiguration extends BaseObject implements
- Serializable {
-
- private static final long serialVersionUID = 1L;
-
- public static final int NO_COLUMN_NAME_LINE = 0;
- public static final int DEFAULT_COLUMN_NAME_LINE = 1;
-
- private final int columnNameLineNumber;
- private final boolean skipEmptyLines;
- private final boolean skipEmptyColumns;
-
- public ExcelConfiguration() {
- this(DEFAULT_COLUMN_NAME_LINE, true, false);
- }
-
- public ExcelConfiguration(int columnNameLineNumber, boolean skipEmptyLines,
- boolean skipEmptyColumns) {
- this.columnNameLineNumber = columnNameLineNumber;
- this.skipEmptyLines = skipEmptyLines;
- this.skipEmptyColumns = skipEmptyColumns;
- }
-
- /**
- * The line number (1 based) from which to get the names of the columns.
- * Note that this line number is affected by the skipEmptyLines property! If
- * skipEmptyLines is set to true, the line numbers will begin from the first
- * non-empty line.
- *
- * @return the line number of the column headers/names.
- */
- public int getColumnNameLineNumber() {
- return columnNameLineNumber;
- }
-
- /**
- * Defines if empty lines in the excel spreadsheet should be skipped while
- * reading the spreadsheet.
- *
- * @return a boolean indicating whether or not to skip empty lines.
- */
- public boolean isSkipEmptyLines() {
- return skipEmptyLines;
- }
-
- /**
- * Defines if empty columns in the excel spreadsheet should be skipped while
- * reading the spreadsheet.
- *
- * @return a boolean indicating whether or not to skip empty columns.
- */
- public boolean isSkipEmptyColumns() {
- return skipEmptyColumns;
- }
-
- @Override
- protected void decorateIdentity(List<Object> identifiers) {
- identifiers.add(columnNameLineNumber);
- identifiers.add(skipEmptyLines);
- identifiers.add(skipEmptyColumns);
- }
-
- @Override
- public String toString() {
- return "ExcelConfiguration[columnNameLineNumber="
- + columnNameLineNumber + ", skipEmptyLines=" + skipEmptyLines
- + ", skipEmptyColumns=" + skipEmptyColumns + "]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDataContext.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDataContext.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDataContext.java
deleted file mode 100644
index 6726d8b..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDataContext.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-
-import org.apache.poi.POIXMLDocument;
-import org.eobjects.metamodel.DataContext;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.QueryPostprocessDataContext;
-import org.eobjects.metamodel.UpdateScript;
-import org.eobjects.metamodel.UpdateableDataContext;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.util.FileHelper;
-import org.eobjects.metamodel.util.FileResource;
-import org.eobjects.metamodel.util.LazyRef;
-import org.eobjects.metamodel.util.Ref;
-import org.eobjects.metamodel.util.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * {@link DataContext} implementation to use for Excel spreadsheets.
- *
- * This DataContext supports both the "old" .xls format and the "new" .xlsx
- * format, and saves the user the trouble of figuring out which one to use,
- * simply by detecting it at runtime and delegating to the appropriate
- * implementation.
- */
-public final class ExcelDataContext extends QueryPostprocessDataContext implements UpdateableDataContext {
-
- private static final Logger logger = LoggerFactory.getLogger(ExcelDataContext.class);
-
- private final Object WRITE_LOCK = new Object();
-
- private final Resource _resource;
- private final ExcelConfiguration _configuration;
- private SpreadsheetReaderDelegate _spreadsheetReaderDelegate;
-
- /**
- * Constructs an Excel DataContext based on a file, with default
- * configuration
- *
- * @param file
- */
- public ExcelDataContext(File file) {
- this(file, new ExcelConfiguration());
- }
-
- /**
- * Constructs an Excel DataContext based on a resource and a custom
- * configuration.
- *
- * @param file
- * @param configuration
- */
- public ExcelDataContext(File file, ExcelConfiguration configuration) {
- if (file == null) {
- throw new IllegalArgumentException("File cannot be null");
- }
- if (configuration == null) {
- throw new IllegalArgumentException("ExcelConfiguration cannot be null");
- }
- if (file.exists() && !file.canRead()) {
- throw new IllegalArgumentException("Cannot read from file");
- }
- _resource = new FileResource(file);
- _configuration = configuration;
- }
-
- public ExcelDataContext(Resource resource, ExcelConfiguration configuration) {
- if (resource == null) {
- throw new IllegalArgumentException("Resource cannot be null");
- }
- if (configuration == null) {
- throw new IllegalArgumentException("ExcelConfiguration cannot be null");
- }
- _resource = resource;
- _configuration = configuration;
- }
-
- /**
- * Gets the Excel configuration used.
- *
- * @return an excel configuration.
- */
- public ExcelConfiguration getConfiguration() {
- return _configuration;
- }
-
- /**
- * Gets the Excel file being read.
- *
- * @return a file.
- * @deprecated
- */
- @Deprecated
- public File getFile() {
- if (_resource instanceof FileResource) {
- return ((FileResource) _resource).getFile();
- }
- return null;
- }
-
- /**
- * Gets the Excel resource being read
- *
- * @return
- */
- public Resource getResource() {
- return _resource;
- }
-
- @Override
- protected String getMainSchemaName() throws MetaModelException {
- return _resource.getName();
- }
-
- @Override
- public DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows) {
-
- Ref<InputStream> inputStreamRef = getInputStreamRef();
- InputStream inputStream = null;
- try {
- SpreadsheetReaderDelegate delegate = getSpreadsheetReaderDelegate(inputStreamRef);
- inputStream = inputStreamRef.get();
- DataSet dataSet = delegate.executeQuery(inputStream, table, columns, maxRows);
- return dataSet;
- } catch (Exception e) {
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- }
- throw new MetaModelException("Unexpected exception while materializing main schema table", e);
- } finally {
- FileHelper.safeClose(inputStream);
- }
- }
-
- @Override
- protected Schema getMainSchema() throws MetaModelException {
- if (!_resource.isExists()) {
- logger.info("Resource does not exist, returning empty schema");
- return new MutableSchema(getMainSchemaName());
- }
- Ref<InputStream> inputStreamRef = getInputStreamRef();
- InputStream inputStream = null;
- try {
- SpreadsheetReaderDelegate delegate = getSpreadsheetReaderDelegate(inputStreamRef);
- inputStream = inputStreamRef.get();
- Schema schema = delegate.createSchema(inputStream, getMainSchemaName());
- assert getMainSchemaName().equals(schema.getName());
- return schema;
- } catch (Exception e) {
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- }
- throw new MetaModelException("Unexpected exception while building main schema", e);
- } finally {
- FileHelper.safeClose(inputStream);
- }
- }
-
- /**
- * Convenient method for testing and inspecting internal state.
- *
- * @return the class of the spreadsheet reader delegate.
- */
- protected Class<? extends SpreadsheetReaderDelegate> getSpreadsheetReaderDelegateClass() {
- if (_spreadsheetReaderDelegate != null) {
- return _spreadsheetReaderDelegate.getClass();
- }
- return null;
- }
-
- private SpreadsheetReaderDelegate getSpreadsheetReaderDelegate(Ref<InputStream> inputStream) throws MetaModelException {
- if (_spreadsheetReaderDelegate == null) {
- synchronized (this) {
- if (_spreadsheetReaderDelegate == null) {
- try {
- if (POIXMLDocument.hasOOXMLHeader(inputStream.get())) {
- _spreadsheetReaderDelegate = new XlsxSpreadsheetReaderDelegate(_configuration);
- } else {
- _spreadsheetReaderDelegate = new DefaultSpreadsheetReaderDelegate(_configuration);
- }
- } catch (IOException e) {
- logger.error("Could not identify spreadsheet type, using default", e);
- _spreadsheetReaderDelegate = new DefaultSpreadsheetReaderDelegate(_configuration);
- }
- }
- }
- }
- return _spreadsheetReaderDelegate;
- }
-
- private InputStream getInputStream() throws MetaModelException {
- InputStream inputStream = _resource.read();
- if (!inputStream.markSupported()) {
- inputStream = new PushbackInputStream(inputStream, 8);
- }
- return inputStream;
- }
-
- private LazyRef<InputStream> getInputStreamRef() throws MetaModelException {
- final LazyRef<InputStream> inputStreamRef = new LazyRef<InputStream>() {
- @Override
- public InputStream fetch() {
- InputStream inputStream = getInputStream();
- return inputStream;
- }
- };
- return inputStreamRef;
- }
-
- protected void notifyTablesModified() {
- LazyRef<InputStream> inputStreamRef = getInputStreamRef();
- try {
- getSpreadsheetReaderDelegate(inputStreamRef).notifyTablesModified(inputStreamRef);
- } finally {
- if (inputStreamRef.isFetched()) {
- FileHelper.safeClose(inputStreamRef.get());
- }
- }
- }
-
- @Override
- public void executeUpdate(UpdateScript update) {
- ExcelUpdateCallback updateCallback = new ExcelUpdateCallback(this);
- synchronized (WRITE_LOCK) {
- try {
- update.run(updateCallback);
- } finally {
- updateCallback.close();
- }
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDeleteBuilder.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDeleteBuilder.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDeleteBuilder.java
deleted file mode 100644
index cd2a0cc..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDeleteBuilder.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.MetaModelHelper;
-import org.eobjects.metamodel.data.DataSetHeader;
-import org.eobjects.metamodel.data.DefaultRow;
-import org.eobjects.metamodel.data.SimpleDataSetHeader;
-import org.eobjects.metamodel.delete.AbstractRowDeletionBuilder;
-import org.eobjects.metamodel.query.SelectItem;
-import org.eobjects.metamodel.schema.Table;
-
-final class ExcelDeleteBuilder extends AbstractRowDeletionBuilder {
-
- private final ExcelUpdateCallback _updateCallback;
-
- public ExcelDeleteBuilder(ExcelUpdateCallback updateCallback, Table table) {
- super(table);
- _updateCallback = updateCallback;
- }
-
- @Override
- public void execute() throws MetaModelException {
- // close the update callback will flush any changes
- _updateCallback.close();
-
- // read the workbook without streaming, since this will not wrap it in a
- // streaming workbook implementation (which do not support random
- // accessing rows).
- final Workbook workbook = _updateCallback.getWorkbook(false);
-
- final String tableName = getTable().getName();
- final SelectItem[] selectItems = MetaModelHelper.createSelectItems(getTable().getColumns());
- final DataSetHeader header = new SimpleDataSetHeader(selectItems);
- final Sheet sheet = workbook.getSheet(tableName);
-
- final Iterator<Row> rowIterator = ExcelUtils.getRowIterator(sheet, _updateCallback.getConfiguration(), true);
- final List<Row> rowsToDelete = new ArrayList<Row>();
- while (rowIterator.hasNext()) {
- final Row excelRow = rowIterator.next();
- final DefaultRow row = ExcelUtils.createRow(workbook, excelRow, header);
-
- final boolean deleteRow = deleteRow(row);
- if (deleteRow) {
- rowsToDelete.add(excelRow);
- }
- }
-
- // reverse the list to not mess up any row numbers
- Collections.reverse(rowsToDelete);
-
- for (Row row : rowsToDelete) {
- sheet.removeRow(row);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDropTableBuilder.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDropTableBuilder.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDropTableBuilder.java
deleted file mode 100644
index abcb222..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelDropTableBuilder.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.drop.AbstractTableDropBuilder;
-import org.eobjects.metamodel.drop.TableDropBuilder;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.Table;
-
-final class ExcelDropTableBuilder extends AbstractTableDropBuilder implements TableDropBuilder {
-
- private ExcelUpdateCallback _updateCallback;
-
- public ExcelDropTableBuilder(ExcelUpdateCallback updateCallback, Table table) {
- super(table);
- _updateCallback = updateCallback;
- }
-
- @Override
- public void execute() throws MetaModelException {
- final Table table = getTable();
- _updateCallback.removeSheet(table.getName());
- final MutableSchema schema = (MutableSchema) table.getSchema();
- schema.removeTable(table);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelInsertBuilder.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelInsertBuilder.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelInsertBuilder.java
deleted file mode 100644
index 24bf3b1..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelInsertBuilder.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import java.util.Date;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Row;
-import org.eobjects.metamodel.data.Style;
-import org.eobjects.metamodel.data.Style.Color;
-import org.eobjects.metamodel.data.Style.SizeUnit;
-import org.eobjects.metamodel.data.Style.TextAlignment;
-import org.eobjects.metamodel.insert.AbstractRowInsertionBuilder;
-import org.eobjects.metamodel.insert.RowInsertionBuilder;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.util.LazyRef;
-
-/**
- * {@link RowInsertionBuilder} for excel spreadsheets.
- *
- * @author Kasper Sørensen
- */
-final class ExcelInsertBuilder extends
- AbstractRowInsertionBuilder<ExcelUpdateCallback> {
-
- public ExcelInsertBuilder(ExcelUpdateCallback updateCallback, Table table) {
- super(updateCallback, table);
- }
-
- @Override
- public void execute() {
- final Object[] values = getValues();
- final Style[] styles = getStyles();
-
- final Row row = getUpdateCallback().createRow(getTable().getName());
-
- final Column[] columns = getColumns();
- for (int i = 0; i < columns.length; i++) {
- Object value = values[i];
- if (value != null) {
- int columnNumber = columns[i].getColumnNumber();
- Cell cell = row.createCell(columnNumber);
-
- // use a lazyref and the isFetched method to only create style
- // if nescesary
- LazyRef<CellStyle> cellStyle = new LazyRef<CellStyle>() {
- @Override
- protected CellStyle fetch() {
- return getUpdateCallback().createCellStyle();
- }
- };
-
- if (value instanceof Number) {
- cell.setCellValue(((Number) value).doubleValue());
- } else if (value instanceof Boolean) {
- cell.setCellValue((Boolean) value);
- } else if (value instanceof Date) {
- cell.setCellValue((Date) value);
- } else {
- cell.setCellValue(value.toString());
- }
-
- Style style = styles[i];
- if (style != null && !Style.NO_STYLE.equals(style)) {
- LazyRef<Font> font = new LazyRef<Font>() {
- @Override
- protected Font fetch() {
- return getUpdateCallback().createFont();
- }
-
- };
- if (style.isBold()) {
- font.get().setBoldweight(Font.BOLDWEIGHT_BOLD);
- }
- if (style.isItalic()) {
- font.get().setItalic(true);
- }
- if (style.isUnderline()) {
- font.get().setUnderline(Font.U_SINGLE);
- }
- if (style.getFontSize() != null) {
- Integer fontSize = style.getFontSize();
- SizeUnit sizeUnit = style.getFontSizeUnit();
- if (sizeUnit == SizeUnit.PERCENT) {
- fontSize = convertFontPercentageToPt(fontSize);
- }
- font.get().setFontHeightInPoints(fontSize.shortValue());
- }
- Color foregroundColor = style.getForegroundColor();
- if (foregroundColor != null) {
- short index = getUpdateCallback().getColorIndex(
- foregroundColor);
- font.get().setColor(index);
- }
- if (font.isFetched()) {
- cellStyle.get().setFont(font.get());
- }
- if (style.getAlignment() != null) {
- cellStyle.get().setAlignment(
- getAlignment(style.getAlignment()));
- }
-
- final Color backgroundColor = style.getBackgroundColor();
- if (backgroundColor != null) {
- cellStyle.get().setFillPattern(
- CellStyle.SOLID_FOREGROUND);
- cellStyle.get().setFillForegroundColor(
- getUpdateCallback().getColorIndex(
- backgroundColor));
- }
- }
-
- if (value instanceof Date) {
- if (cellStyle.isFetched()) {
- cellStyle.get().setDataFormat(
- getUpdateCallback().getDateCellFormat());
- } else {
- cellStyle = new LazyRef<CellStyle>() {
- @Override
- protected CellStyle fetch() {
- return getUpdateCallback().getDateCellStyle();
- }
- };
- // trigger the fetch
- cellStyle.get();
- }
- }
-
- if (cellStyle.isFetched()) {
- cell.setCellStyle(cellStyle.get());
- }
- }
- }
- }
-
- /**
- * Converts a percentage based font size to excel "pt" scale.
- *
- * @param percentage
- * @return
- */
- private Integer convertFontPercentageToPt(Integer percentage) {
- Double d = percentage.intValue() * 11.0 / 100;
- return d.intValue();
- }
-
- private short getAlignment(TextAlignment alignment) {
- switch (alignment) {
- case LEFT:
- return CellStyle.ALIGN_LEFT;
- case RIGHT:
- return CellStyle.ALIGN_RIGHT;
- case CENTER:
- return CellStyle.ALIGN_CENTER;
- case JUSTIFY:
- return CellStyle.ALIGN_JUSTIFY;
- default:
- throw new IllegalArgumentException("Unknown alignment type: "
- + alignment);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelTableCreationBuilder.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelTableCreationBuilder.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelTableCreationBuilder.java
deleted file mode 100644
index a031fde..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelTableCreationBuilder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
-import org.eobjects.metamodel.create.TableCreationBuilder;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.MutableTable;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-
-/**
- * {@link TableCreationBuilder} implementation for Excel spreadsheets.
- *
- * @author Kasper Sørensen
- */
-final class ExcelTableCreationBuilder extends AbstractTableCreationBuilder<ExcelUpdateCallback> {
-
- public ExcelTableCreationBuilder(ExcelUpdateCallback updateCallback, Schema schema, String name) {
- super(updateCallback, schema, name);
- }
-
- @Override
- public Table execute() {
- final ExcelUpdateCallback updateCallback = getUpdateCallback();
- final MutableTable table = getTable();
-
- final Sheet sheet = updateCallback.createSheet(table.getName());
-
- final int lineNumber = updateCallback.getConfiguration().getColumnNameLineNumber();
- if (lineNumber != ExcelConfiguration.NO_COLUMN_NAME_LINE) {
- final int zeroBasedLineNumber = lineNumber - 1;
- final Row row = sheet.createRow(zeroBasedLineNumber);
- final Column[] columns = table.getColumns();
- for (int i = 0; i < columns.length; i++) {
- final Column column = columns[i];
- final int columnNumber = column.getColumnNumber();
- row.createCell(columnNumber).setCellValue(column.getName());
- }
- }
-
- final MutableSchema schema = (MutableSchema) table.getSchema();
- schema.addTable((MutableTable) table);
- return table;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelUpdateCallback.java
----------------------------------------------------------------------
diff --git a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelUpdateCallback.java b/excel/src/main/java/org/eobjects/metamodel/excel/ExcelUpdateCallback.java
deleted file mode 100644
index 9564ba9..0000000
--- a/excel/src/main/java/org/eobjects/metamodel/excel/ExcelUpdateCallback.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.eobjects.metamodel.excel;
-
-import org.apache.poi.hssf.usermodel.HSSFPalette;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Font;
-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.streaming.SXSSFSheet;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.eobjects.metamodel.AbstractUpdateCallback;
-import org.eobjects.metamodel.UpdateCallback;
-import org.eobjects.metamodel.create.TableCreationBuilder;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.data.Style.Color;
-import org.eobjects.metamodel.delete.RowDeletionBuilder;
-import org.eobjects.metamodel.drop.TableDropBuilder;
-import org.eobjects.metamodel.insert.RowInsertionBuilder;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-
-final class ExcelUpdateCallback extends AbstractUpdateCallback implements UpdateCallback {
-
- private final ExcelDataContext _dataContext;
- private final ExcelConfiguration _configuration;
- private boolean _sheetsModified;
- private Workbook _workbook;
- private Short _dateCellFormat;
- private CellStyle _dateCellStyle;
-
- public ExcelUpdateCallback(ExcelDataContext dataContext) {
- super(dataContext);
- _sheetsModified = false;
- _configuration = dataContext.getConfiguration();
- _dataContext = dataContext;
- }
-
- @Override
- public TableCreationBuilder createTable(Schema schema, String name) throws IllegalArgumentException,
- IllegalStateException {
- return new ExcelTableCreationBuilder(this, schema, name);
- }
-
- @Override
- public RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException {
- return new ExcelInsertBuilder(this, table);
- }
-
- protected ExcelConfiguration getConfiguration() {
- return _configuration;
- }
-
- @Override
- public ExcelDataContext getDataContext() {
- return _dataContext;
- }
-
- protected void close() {
- if (_workbook != null) {
- ExcelUtils.writeWorkbook(_dataContext, _workbook);
-
- _workbook = null;
- _dateCellFormat = null;
- _dateCellStyle = null;
- }
- if (_sheetsModified) {
- _dataContext.notifyTablesModified();
- _sheetsModified = false;
- }
- }
-
- protected Workbook getWorkbook(boolean streamingAllowed) {
- if (_workbook == null || (!streamingAllowed && _workbook instanceof SXSSFWorkbook)) {
- if (_workbook != null) {
- ExcelUtils.writeWorkbook(_dataContext, _workbook);
- }
- _workbook = ExcelUtils.readWorkbook(_dataContext);
- if (streamingAllowed && _workbook instanceof XSSFWorkbook) {
- _workbook = new SXSSFWorkbook((XSSFWorkbook) _workbook);
- }
- }
- return _workbook;
- }
-
- protected Sheet createSheet(String name) {
- Sheet sheet = getWorkbook(true).createSheet(name);
- _sheetsModified = true;
- return sheet;
- }
-
- protected void removeSheet(String name) {
- int index = getWorkbook(true).getSheetIndex(name);
- if (index != -1) {
- getWorkbook(true).removeSheetAt(index);
- _sheetsModified = true;
- }
- }
-
- protected Row createRow(String name) {
- if (_sheetsModified) {
- close();
- }
- Sheet sheet = getWorkbook(true).getSheet(name);
- int lastRowNum = getLastRowNum(sheet);
- Row row = sheet.createRow(lastRowNum + 1);
- return row;
- }
-
- private int getLastRowNum(Sheet sheet) {
- final int lastRowNum = sheet.getLastRowNum();
- if (lastRowNum == 0 && sheet instanceof SXSSFSheet) {
- // streaming sheets have bad behaviour in this scenario - since no
- // rows are in cache, it will return 0!
- DataSet ds = _dataContext.query().from(sheet.getSheetName()).selectCount().execute();
- ds.next();
- final Number count = (Number) ds.getRow().getValue(0);
- final int columnNameLineNumber = _configuration.getColumnNameLineNumber();
- int oneBasedResult = count.intValue()
- + (columnNameLineNumber == ExcelConfiguration.NO_COLUMN_NAME_LINE ? 0 : columnNameLineNumber);
- return oneBasedResult - 1;
- }
- return lastRowNum;
- }
-
- /**
- * Creates a new cell style in the spreadsheet
- *
- * @return
- */
- public CellStyle createCellStyle() {
- Workbook workbook = getWorkbook(true);
- return workbook.createCellStyle();
- }
-
- public Font createFont() {
- Workbook workbook = getWorkbook(true);
- return workbook.createFont();
- }
-
- protected Sheet getSheet(String name) {
- return getWorkbook(true).getSheet(name);
- }
-
- /**
- * Gets the index identifier for the date format
- *
- * @return
- */
- public short getDateCellFormat() {
- if (_dateCellFormat == null) {
- Workbook workbook = getWorkbook(true);
- _dateCellFormat = workbook.getCreationHelper().createDataFormat().getFormat("m/d/yy h:mm");
- }
- return _dateCellFormat;
- }
-
- /**
- * Gets a shared, reusable cell style for "pure date" cells (eg. no other
- * styling applied)
- *
- * @return
- */
- public CellStyle getDateCellStyle() {
- if (_dateCellStyle == null) {
- _dateCellStyle = createCellStyle();
- _dateCellStyle.setDataFormat(getDateCellFormat());
- }
- return _dateCellStyle;
- }
-
- public short getColorIndex(Color color) {
- Workbook workbook = getWorkbook(true);
- if (workbook instanceof HSSFWorkbook) {
- HSSFPalette palette = ((HSSFWorkbook) workbook).getCustomPalette();
- byte r = toRgb(color.getRed());
- byte g = toRgb(color.getGreen());
- byte b = toRgb(color.getBlue());
-
- HSSFColor index = palette.findColor(r, g, b);
- if (index == null) {
- index = palette.findSimilarColor(r, g, b);
- }
- return index.getIndex();
- }
- throw new IllegalStateException("Unexpected workbook type: " + workbook.getClass());
- }
-
- private byte toRgb(int i) {
- assert i >= 0;
- assert i <= 255;
-
- if (i > 127) {
- i = i - 256;
- }
- return (byte) i;
- }
-
- @Override
- public boolean isDropTableSupported() {
- return true;
- }
-
- @Override
- public TableDropBuilder dropTable(Table table) throws UnsupportedOperationException {
- return new ExcelDropTableBuilder(this, table);
- }
-
- @Override
- public boolean isDeleteSupported() {
- return true;
- }
-
- @Override
- public RowDeletionBuilder deleteFrom(Table table) throws UnsupportedOperationException {
- return new ExcelDeleteBuilder(this, table);
- }
-}