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:30 UTC
[17/64] [partial] Hard rename of all 'org/eobjects' folders to
'org/apache'.
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/test/java/org/eobjects/metamodel/couchdb/CouchDbDataContextTest.java
----------------------------------------------------------------------
diff --git a/couchdb/src/test/java/org/eobjects/metamodel/couchdb/CouchDbDataContextTest.java b/couchdb/src/test/java/org/eobjects/metamodel/couchdb/CouchDbDataContextTest.java
deleted file mode 100644
index 403a64c..0000000
--- a/couchdb/src/test/java/org/eobjects/metamodel/couchdb/CouchDbDataContextTest.java
+++ /dev/null
@@ -1,354 +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.couchdb;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.TestCase;
-
-import org.ektorp.CouchDbConnector;
-import org.ektorp.DbAccessException;
-import org.ektorp.http.HttpClient;
-import org.ektorp.http.StdHttpClient;
-import org.ektorp.impl.StdCouchDbInstance;
-import org.eobjects.metamodel.UpdateCallback;
-import org.eobjects.metamodel.UpdateScript;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.data.Row;
-import org.eobjects.metamodel.drop.DropTable;
-import org.eobjects.metamodel.insert.InsertInto;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.ColumnType;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.util.SimpleTableDef;
-
-public class CouchDbDataContextTest extends TestCase {
-
- private static final String TEST_DATABASE_NAME = "eobjects_metamodel_test";
-
- private boolean serverAvailable;
-
- private HttpClient httpClient;
- private StdCouchDbInstance couchDbInstance;
- private CouchDbConnector connector;
- private SimpleTableDef predefinedTableDef;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- httpClient = new StdHttpClient.Builder().host("localhost").build();
-
- // set up a simple database
- couchDbInstance = new StdCouchDbInstance(httpClient);
-
- try {
- if (couchDbInstance.getAllDatabases().contains(TEST_DATABASE_NAME)) {
- throw new IllegalStateException("Couch DB instance already has a database called " + TEST_DATABASE_NAME);
- }
- connector = couchDbInstance.createConnector(TEST_DATABASE_NAME, true);
- System.out.println("Running CouchDB integration tests");
- serverAvailable = true;
- } catch (DbAccessException e) {
- System.out.println("!!! WARNING: Skipping CouchDB tests because local server is not available");
- e.printStackTrace();
- serverAvailable = false;
- }
-
- final String[] columnNames = new String[] { "name", "gender", "age" };
- final ColumnType[] columnTypes = new ColumnType[] { ColumnType.VARCHAR, ColumnType.CHAR, ColumnType.INTEGER };
- predefinedTableDef = new SimpleTableDef(TEST_DATABASE_NAME, columnNames, columnTypes);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- connector = null;
-
- if (serverAvailable) {
- couchDbInstance.deleteDatabase(TEST_DATABASE_NAME);
- }
-
- httpClient.shutdown();
- }
-
- public void testWorkingWithMapsAndLists() throws Exception {
- if (!serverAvailable) {
- return;
- }
-
- connector = couchDbInstance.createConnector("test_table_map_and_list", true);
-
- final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, new SimpleTableDef("test_table_map_and_list",
- new String[] { "id", "foo", "bar" }, new ColumnType[] { ColumnType.INTEGER, ColumnType.MAP, ColumnType.LIST }));
- Table table = null;
- try {
- table = dc.getTableByQualifiedLabel("test_table_map_and_list");
- Map<String, Object> exampleMap = new LinkedHashMap<String, Object>();
- exampleMap.put("hello", Arrays.asList("world", "welt", "verden"));
- exampleMap.put("foo", "bar");
-
- List<Map<String, Object>> exampleList = new ArrayList<Map<String, Object>>();
- exampleList.add(new LinkedHashMap<String, Object>());
- Map<String, Object> exampleMap2 = new LinkedHashMap<String, Object>();
- exampleMap2.put("meta", "model");
- exampleMap2.put("couch", "db");
- exampleList.add(exampleMap2);
-
- dc.executeUpdate(new InsertInto(table).value("id", 1).value("foo", exampleMap).value("bar", exampleList));
-
- DataSet ds = dc.query().from(table).select("id","foo","bar").execute();
- assertTrue(ds.next());
- Row row = ds.getRow();
- assertFalse(ds.next());
- ds.close();
-
- assertEquals(
- "Row[values=[1, {hello=[world, welt, verden], foo=bar}, [{}, {meta=model, couch=db}]]]",
- row.toString());
- assertTrue(row.getValue(0) instanceof Integer);
- assertTrue(row.getValue(1) instanceof Map);
- assertTrue(row.getValue(2) instanceof List);
-
- } finally {
- dc.executeUpdate(new DropTable(table));
- }
-
- }
-
- public void testCreateUpdateDeleteScenario() throws Exception {
- if (!serverAvailable) {
- return;
- }
-
- final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance);
-
- // first delete the manually created database!
- dc.executeUpdate(new UpdateScript() {
- @Override
- public void run(UpdateCallback callback) {
- callback.dropTable(TEST_DATABASE_NAME).execute();
- }
- });
-
- assertNull(dc.getDefaultSchema().getTableByName(TEST_DATABASE_NAME));
-
- dc.executeUpdate(new UpdateScript() {
- @Override
- public void run(UpdateCallback callback) {
- Table table = callback.createTable(dc.getDefaultSchema(), TEST_DATABASE_NAME).withColumn("foo")
- .ofType(ColumnType.VARCHAR).withColumn("greeting").ofType(ColumnType.VARCHAR).execute();
- assertEquals("[_id, _rev, foo, greeting]", Arrays.toString(table.getColumnNames()));
- }
- });
-
- dc.executeUpdate(new UpdateScript() {
- @Override
- public void run(UpdateCallback callback) {
- callback.insertInto(TEST_DATABASE_NAME).value("foo", "bar").value("greeting", "hello").execute();
- callback.insertInto(TEST_DATABASE_NAME).value("foo", "baz").value("greeting", "hi").execute();
- }
- });
-
- DataSet ds = dc.query().from(TEST_DATABASE_NAME).select("_id", "foo", "greeting").execute();
- assertTrue(ds.next());
- assertNotNull(ds.getRow().getValue(0));
- assertEquals("bar", ds.getRow().getValue(1));
- assertEquals("hello", ds.getRow().getValue(2));
- assertTrue(ds.next());
- assertNotNull(ds.getRow().getValue(0));
- assertEquals("baz", ds.getRow().getValue(1));
- assertEquals("hi", ds.getRow().getValue(2));
- assertFalse(ds.next());
- ds.close();
-
- dc.executeUpdate(new UpdateScript() {
- @Override
- public void run(UpdateCallback callback) {
- callback.update(TEST_DATABASE_NAME).value("greeting", "howdy").where("foo").isEquals("baz").execute();
-
- callback.update(TEST_DATABASE_NAME).value("foo", "foo").where("foo").isEquals("bar").execute();
- }
- });
-
- ds = dc.query().from(TEST_DATABASE_NAME).select("_id", "foo", "greeting").execute();
- assertTrue(ds.next());
- assertNotNull(ds.getRow().getValue(0));
- assertEquals("foo", ds.getRow().getValue(1));
- assertEquals("hello", ds.getRow().getValue(2));
- assertTrue(ds.next());
- assertNotNull(ds.getRow().getValue(0));
- assertEquals("baz", ds.getRow().getValue(1));
- assertEquals("howdy", ds.getRow().getValue(2));
- assertFalse(ds.next());
- ds.close();
- }
-
- public void testBasicQuery() throws Exception {
- if (!serverAvailable) {
- return;
- }
-
- // insert a few records
- {
- HashMap<String, Object> map;
-
- map = new HashMap<String, Object>();
- map.put("name", "John Doe");
- map.put("age", 30);
- connector.create(map);
-
- map = new HashMap<String, Object>();
- map.put("name", "Jane Doe");
- map.put("gender", 'F');
- connector.create(map);
- }
-
- // create datacontext using detected schema
- SimpleTableDef tableDef = CouchDbDataContext.detectTable(connector);
- CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, tableDef);
-
- // verify schema and execute query
- Schema schema = dc.getMainSchema();
- assertEquals("[eobjects_metamodel_test]", Arrays.toString(schema.getTableNames()));
-
- assertEquals("[_id, _rev, age, gender, name]",
- Arrays.toString(schema.getTableByName(TEST_DATABASE_NAME).getColumnNames()));
- Column idColumn = schema.getTableByName(TEST_DATABASE_NAME).getColumnByName("_id");
- assertEquals("Column[name=_id,columnNumber=0,type=VARCHAR,nullable=true,nativeType=null,columnSize=null]",
- idColumn.toString());
- assertTrue(idColumn.isPrimaryKey());
-
- assertEquals("Column[name=_rev,columnNumber=1,type=VARCHAR,nullable=true,nativeType=null,columnSize=null]", schema
- .getTableByName(TEST_DATABASE_NAME).getColumnByName("_rev").toString());
-
- DataSet ds;
-
- ds = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").execute();
- assertTrue(ds.next());
- assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString());
- assertTrue(ds.next());
- assertEquals("Row[values=[Jane Doe, null]]", ds.getRow().toString());
- assertFalse(ds.next());
- ds.close();
-
- ds = dc.query().from(TEST_DATABASE_NAME).select("name").and("gender").where("age").isNull().execute();
- assertTrue(ds.next());
- assertEquals("Row[values=[Jane Doe, F]]", ds.getRow().toString());
- assertFalse(ds.next());
- ds.close();
- }
-
- public void testFirstRowAndLastRow() throws Exception {
- if (!serverAvailable) {
- return;
- }
-
- // insert a few records
- {
- HashMap<String, Object> map;
-
- map = new HashMap<String, Object>();
- map.put("name", "John Doe");
- map.put("age", 30);
- connector.create(map);
-
- map = new HashMap<String, Object>();
- map.put("name", "Jane Doe");
- map.put("gender", 'F');
- connector.create(map);
- }
-
- // create datacontext using detected schema
- SimpleTableDef tableDef = CouchDbDataContext.detectTable(connector);
- CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, tableDef);
-
- DataSet ds1 = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").firstRow(2).execute();
- DataSet ds2 = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").maxRows(1).execute();
-
- assertTrue("Class: " + ds1.getClass().getName(), ds1 instanceof CouchDbDataSet);
- assertTrue("Class: " + ds2.getClass().getName(), ds2 instanceof CouchDbDataSet);
-
- assertTrue(ds1.next());
- assertTrue(ds2.next());
-
- final Row row1 = ds1.getRow();
- final Row row2 = ds2.getRow();
-
- assertFalse(ds1.next());
- assertFalse(ds2.next());
-
- assertEquals("Row[values=[Jane Doe, null]]", row1.toString());
- assertEquals("Row[values=[John Doe, 30]]", row2.toString());
-
- ds1.close();
- ds2.close();
- }
-
- public void testInsert() throws Exception {
- if (!serverAvailable) {
- return;
- }
-
- // create datacontext using predefined table def
- CouchDbDataContext dc = new CouchDbDataContext(httpClient, predefinedTableDef);
- Table table = dc.getTableByQualifiedLabel(TEST_DATABASE_NAME);
- assertNotNull(table);
-
- assertEquals("[_id, _rev, name, gender, age]", Arrays.toString(table.getColumnNames()));
-
- DataSet ds;
-
- // assert not rows in DB
- ds = dc.query().from(TEST_DATABASE_NAME).selectCount().execute();
- assertTrue(ds.next());
- assertEquals(0, ((Number) ds.getRow().getValue(0)).intValue());
- assertFalse(ds.next());
- ds.close();
-
- dc.executeUpdate(new UpdateScript() {
- @Override
- public void run(UpdateCallback callback) {
- callback.insertInto(TEST_DATABASE_NAME).value("name", "foo").value("gender", 'M').execute();
- callback.insertInto(TEST_DATABASE_NAME).value("name", "bar").value("age", 32).execute();
- }
- });
-
- // now count should be 2
- ds = dc.query().from(TEST_DATABASE_NAME).selectCount().execute();
- assertTrue(ds.next());
- assertEquals(2, ((Number) ds.getRow().getValue(0)).intValue());
- assertFalse(ds.next());
- ds.close();
-
- ds = dc.query().from(TEST_DATABASE_NAME).select("name", "gender", "age").execute();
- assertTrue(ds.next());
- assertEquals("Row[values=[foo, M, null]]", ds.getRow().toString());
- assertTrue(ds.next());
- assertEquals("Row[values=[bar, null, 32]]", ds.getRow().toString());
- assertFalse(ds.next());
- ds.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvConfiguration.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvConfiguration.java b/csv/src/main/java/org/apache/metamodel/csv/CsvConfiguration.java
new file mode 100644
index 0000000..8e34913
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvConfiguration.java
@@ -0,0 +1,160 @@
+/**
+ * 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.csv;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.eobjects.metamodel.util.BaseObject;
+import org.eobjects.metamodel.util.FileHelper;
+
+/**
+ * Represents the configuration for reading/parsing CSV files.
+ *
+ * @author Kasper Sørensen
+ */
+public final class CsvConfiguration extends BaseObject implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The value is '\\uFFFF', the "not a character" value which should not
+ * occur in any valid Unicode string. This special char can be used to
+ * disable either quote chars or escape chars.
+ */
+ public static final char NOT_A_CHAR = '\uFFFF';
+ public static final int NO_COLUMN_NAME_LINE = 0;
+ public static final int DEFAULT_COLUMN_NAME_LINE = 1;
+ public static final char DEFAULT_SEPARATOR_CHAR = ',';
+ public static final char DEFAULT_QUOTE_CHAR = '"';
+ public static final char DEFAULT_ESCAPE_CHAR = '\\';
+
+ private final int columnNameLineNumber;
+ private final String encoding;
+ private final char separatorChar;
+ private final char quoteChar;
+ private final char escapeChar;
+ private final boolean failOnInconsistentRowLength;
+
+ public CsvConfiguration() {
+ this(DEFAULT_COLUMN_NAME_LINE);
+ }
+
+ public CsvConfiguration(int columnNameLineNumber) {
+ this(columnNameLineNumber, FileHelper.DEFAULT_ENCODING,
+ DEFAULT_SEPARATOR_CHAR, DEFAULT_QUOTE_CHAR, DEFAULT_ESCAPE_CHAR);
+ }
+
+ public CsvConfiguration(int columnNameLineNumber, String encoding,
+ char separatorChar, char quoteChar, char escapeChar) {
+ this(columnNameLineNumber, encoding, separatorChar, quoteChar,
+ escapeChar, false);
+ }
+
+ public CsvConfiguration(int columnNameLineNumber, String encoding,
+ char separatorChar, char quoteChar, char escapeChar,
+ boolean failOnInconsistentRowLength) {
+ this.columnNameLineNumber = columnNameLineNumber;
+ this.encoding = encoding;
+ this.separatorChar = separatorChar;
+ this.quoteChar = quoteChar;
+ this.escapeChar = escapeChar;
+ this.failOnInconsistentRowLength = failOnInconsistentRowLength;
+ }
+
+ /**
+ * Determines whether to fail (by throwing an
+ * {@link InconsistentRowLengthException}) if a line in the CSV file has
+ * inconsistent amounts of columns.
+ *
+ * If set to false (default) MetaModel will gracefully fill in missing null
+ * values in or ignore additional values in a line.
+ *
+ * @return a boolean indicating whether to fail or gracefully compensate for
+ * inconsistent lines in the CSV files.
+ */
+ public boolean isFailOnInconsistentRowLength() {
+ return failOnInconsistentRowLength;
+ }
+
+ /**
+ * The line number (1 based) from which to get the names of the columns.
+ *
+ * @return the line number (1 based)
+ */
+ public int getColumnNameLineNumber() {
+ return columnNameLineNumber;
+ }
+
+ /**
+ * Gets the file encoding to use for reading the file.
+ *
+ * @return the text encoding of the file.
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Gets the separator char (typically comma or semicolon) for separating
+ * values.
+ *
+ * @return the separator char
+ */
+ public char getSeparatorChar() {
+ return separatorChar;
+ }
+
+ /**
+ * Gets the quote char, used for encapsulating values.
+ *
+ * @return the quote char
+ */
+ public char getQuoteChar() {
+ return quoteChar;
+ }
+
+ /**
+ * Gets the escape char, used for escaping eg. quote chars inside values.
+ *
+ * @return the escape char
+ */
+ public char getEscapeChar() {
+ return escapeChar;
+ }
+
+ @Override
+ protected void decorateIdentity(List<Object> identifiers) {
+ identifiers.add(columnNameLineNumber);
+ identifiers.add(encoding);
+ identifiers.add(separatorChar);
+ identifiers.add(quoteChar);
+ identifiers.add(escapeChar);
+ identifiers.add(failOnInconsistentRowLength);
+ }
+
+ @Override
+ public String toString() {
+ return "CsvConfiguration[columnNameLineNumber=" + columnNameLineNumber
+ + ", encoding=" + encoding + ", separatorChar=" + separatorChar
+ + ", quoteChar=" + quoteChar + ", escapeChar=" + escapeChar
+ + ", failOnInconsistentRowLength="
+ + failOnInconsistentRowLength + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvCreateTableBuilder.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvCreateTableBuilder.java b/csv/src/main/java/org/apache/metamodel/csv/CsvCreateTableBuilder.java
new file mode 100644
index 0000000..906d2e1
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvCreateTableBuilder.java
@@ -0,0 +1,51 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+
+final class CsvCreateTableBuilder extends
+ AbstractTableCreationBuilder<CsvUpdateCallback> {
+
+ public CsvCreateTableBuilder(CsvUpdateCallback updateCallback,
+ Schema schema, String name) {
+ super(updateCallback, schema, name);
+ if (!(schema instanceof CsvSchema)) {
+ throw new IllegalArgumentException("Not a valid CSV schema: "
+ + schema);
+ }
+ }
+
+ @Override
+ public Table execute() {
+ CsvUpdateCallback csvUpdateCallback = getUpdateCallback();
+
+ MutableTable table = getTable();
+ String[] columnNames = table.getColumnNames();
+ csvUpdateCallback.writeRow(columnNames, false);
+
+ CsvSchema schema = (CsvSchema) table.getSchema();
+ CsvTable csvTable = new CsvTable(schema, table.getColumnNames());
+ schema.setTable(csvTable);
+ return csvTable;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
new file mode 100644
index 0000000..6409596
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContext.java
@@ -0,0 +1,393 @@
+/**
+ * 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.csv;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.util.List;
+
+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.query.FilterItem;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.FileHelper;
+import org.eobjects.metamodel.util.FileResource;
+import org.eobjects.metamodel.util.Func;
+import org.eobjects.metamodel.util.Resource;
+import org.eobjects.metamodel.util.UrlResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import au.com.bytecode.opencsv.CSVReader;
+
+/**
+ * DataContext implementation for reading CSV files.
+ */
+public final class CsvDataContext extends QueryPostprocessDataContext implements UpdateableDataContext {
+
+ private static final Logger logger = LoggerFactory.getLogger(CsvDataContext.class);
+
+ private final Object WRITE_LOCK = new Object();
+
+ private final Resource _resource;
+ private final CsvConfiguration _configuration;
+ private final boolean _writable;
+
+ /**
+ * Constructs a CSV DataContext based on a file
+ *
+ * @param file
+ * @param configuration
+ */
+ public CsvDataContext(File file, CsvConfiguration configuration) {
+ if (file == null) {
+ throw new IllegalArgumentException("File cannot be null");
+ }
+ if (configuration == null) {
+ throw new IllegalArgumentException("CsvConfiguration cannot be null");
+ }
+ _resource = new FileResource(file);
+ _configuration = configuration;
+ _writable = true;
+ }
+
+ public CsvDataContext(Resource resource, CsvConfiguration configuration) {
+ if (resource == null) {
+ throw new IllegalArgumentException("File cannot be null");
+ }
+ if (configuration == null) {
+ throw new IllegalArgumentException("CsvConfiguration cannot be null");
+ }
+ _resource = resource;
+ _configuration = configuration;
+ _writable = !resource.isReadOnly();
+ }
+
+ /**
+ * Constructs a CSV DataContext based on a {@link URL}
+ *
+ * @param url
+ * @param configuration
+ */
+ public CsvDataContext(URL url, CsvConfiguration configuration) {
+ _resource = new UrlResource(url);
+ _configuration = configuration;
+ _writable = false;
+ }
+
+ /**
+ * Constructs a CSV DataContext based on a file
+ *
+ * @param file
+ */
+ public CsvDataContext(File file) {
+ this(file, new CsvConfiguration());
+ }
+
+ /**
+ * Constructs a CSV DataContext based on an {@link InputStream}
+ *
+ * @param inputStream
+ * @param configuration
+ */
+ public CsvDataContext(InputStream inputStream, CsvConfiguration configuration) {
+ File file = createFileFromInputStream(inputStream, configuration.getEncoding());
+ _configuration = configuration;
+ _writable = false;
+ _resource = new FileResource(file);
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
+ */
+ @Deprecated
+ public CsvDataContext(File file, char separatorChar) {
+ this(file, separatorChar, CsvConfiguration.DEFAULT_QUOTE_CHAR);
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
+ */
+ @Deprecated
+ public CsvDataContext(File file, char separatorChar, char quoteChar) {
+ this(file, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, FileHelper.DEFAULT_ENCODING,
+ separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(File, CsvConfiguration)} instead.
+ */
+ @Deprecated
+ public CsvDataContext(File file, char separatorChar, char quoteChar, String encoding) {
+ this(file, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar,
+ CsvConfiguration.DEFAULT_ESCAPE_CHAR));
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(URL, CsvConfiguration)} instead.
+ */
+ @Deprecated
+ public CsvDataContext(URL url, char separatorChar, char quoteChar) {
+ this(url, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(URL, CsvConfiguration)} instead.
+ */
+ @Deprecated
+ public CsvDataContext(URL url, char separatorChar, char quoteChar, String encoding) {
+ this(url, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar,
+ CsvConfiguration.DEFAULT_ESCAPE_CHAR));
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(InputStream, CsvConfiguration)}
+ * instead.
+ */
+ @Deprecated
+ public CsvDataContext(InputStream inputStream, char separatorChar, char quoteChar) {
+ this(inputStream, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, FileHelper.DEFAULT_ENCODING,
+ separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
+ }
+
+ /**
+ * @deprecated use {@link #CsvDataContext(InputStream, CsvConfiguration)}
+ * instead.
+ */
+ @Deprecated
+ public CsvDataContext(InputStream inputStream, char separatorChar, char quoteChar, String encoding) {
+ this(inputStream, new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
+ quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR));
+ }
+
+ /**
+ * Gets the CSV configuration used
+ *
+ * @return a CSV configuration
+ */
+ public CsvConfiguration getConfiguration() {
+ return _configuration;
+ }
+
+ /**
+ * Gets the CSV file being read
+ *
+ * @return a file
+ *
+ * @deprecated use {@link #getResource()} instead.
+ */
+ @Deprecated
+ public File getFile() {
+ if (_resource instanceof FileResource) {
+ return ((FileResource) _resource).getFile();
+ }
+ return null;
+ }
+
+ /**
+ * Gets the resource that is being read from.
+ *
+ * @return
+ */
+ public Resource getResource() {
+ return _resource;
+ }
+
+ private static File createFileFromInputStream(InputStream inputStream, String encoding) {
+ final File file;
+ final File tempDir = FileHelper.getTempDir();
+
+ File fileCandidate = null;
+ boolean usableName = false;
+ int index = 0;
+
+ while (!usableName) {
+ index++;
+ fileCandidate = new File(tempDir, "metamodel" + index + ".csv");
+ usableName = !fileCandidate.exists();
+ }
+ file = fileCandidate;
+
+ final BufferedWriter writer = FileHelper.getBufferedWriter(file, encoding);
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+
+ try {
+ file.createNewFile();
+ file.deleteOnExit();
+
+ boolean firstLine = true;
+
+ for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+ if (firstLine) {
+ firstLine = false;
+ } else {
+ writer.write('\n');
+ }
+ writer.write(line);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ } finally {
+ FileHelper.safeClose(writer, reader);
+ }
+
+ return file;
+ }
+
+ @Override
+ protected Number executeCountQuery(Table table, List<FilterItem> whereItems, boolean functionApproximationAllowed) {
+ if (!functionApproximationAllowed) {
+ return null;
+ }
+
+ return _resource.read(new Func<InputStream, Number>() {
+ @Override
+ public Number eval(InputStream inputStream) {
+ try {
+ final long length = _resource.getSize();
+ // read up to 5 megs of the file and approximate number of
+ // lines
+ // based on that.
+
+ final int sampleSize = (int) Math.min(length, 1024 * 1024 * 5);
+ final int chunkSize = Math.min(sampleSize, 1024 * 1024);
+
+ int readSize = 0;
+ int newlines = 0;
+ int carriageReturns = 0;
+ byte[] byteBuffer = new byte[chunkSize];
+ char[] charBuffer = new char[chunkSize];
+
+ while (readSize < sampleSize) {
+ final int read = inputStream.read(byteBuffer);
+ if (read == -1) {
+ break;
+ } else {
+ readSize += read;
+ }
+
+ Reader reader = getReader(byteBuffer, _configuration.getEncoding());
+ reader.read(charBuffer);
+ for (char c : charBuffer) {
+ if ('\n' == c) {
+ newlines++;
+ } else if ('\r' == c) {
+ carriageReturns++;
+ }
+ }
+ }
+
+ int lines = Math.max(newlines, carriageReturns);
+
+ logger.info("Found {} lines breaks in {} bytes", lines, sampleSize);
+
+ long approxCount = (long) (lines * length / sampleSize);
+ return approxCount;
+ } catch (IOException e) {
+ logger.error("Unexpected error during COUNT(*) approximation", e);
+ throw new IllegalStateException(e);
+ }
+ }
+ });
+ }
+
+ private Reader getReader(byte[] byteBuffer, String encoding) throws UnsupportedEncodingException {
+ try {
+ return new InputStreamReader(new ByteArrayInputStream(byteBuffer), encoding);
+ } catch (UnsupportedEncodingException e1) {
+ // this may happen on more exotic encodings, but since this reader
+ // is only meant for finding newlines, we'll try again with UTF8
+ try {
+ return new InputStreamReader(new ByteArrayInputStream(byteBuffer), "UTF8");
+ } catch (UnsupportedEncodingException e2) {
+ throw e1;
+ }
+ }
+ }
+
+ @Override
+ public DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows) {
+ final int lineNumber = _configuration.getColumnNameLineNumber();
+ final CSVReader reader = createCsvReader(lineNumber);
+ final int columnCount = table.getColumnCount();
+ final boolean failOnInconsistentRowLength = _configuration.isFailOnInconsistentRowLength();
+ if (maxRows < 0) {
+ return new CsvDataSet(reader, columns, null, columnCount, failOnInconsistentRowLength);
+ } else {
+ return new CsvDataSet(reader, columns, maxRows, columnCount, failOnInconsistentRowLength);
+ }
+ }
+
+ protected CSVReader createCsvReader(int skipLines) {
+ final Reader fileReader = FileHelper.getReader(_resource.read(), _configuration.getEncoding());
+ final CSVReader csvReader = new CSVReader(fileReader, _configuration.getSeparatorChar(),
+ _configuration.getQuoteChar(), _configuration.getEscapeChar(), skipLines);
+ return csvReader;
+ }
+
+ @Override
+ protected CsvSchema getMainSchema() throws MetaModelException {
+ CsvSchema schema = new CsvSchema(getMainSchemaName(), this);
+ if (_resource.isExists()) {
+ schema.setTable(new CsvTable(schema));
+ }
+ return schema;
+ }
+
+ @Override
+ protected String getMainSchemaName() {
+ return _resource.getName();
+ }
+
+ protected boolean isWritable() {
+ return _writable;
+ }
+
+ private void checkWritable() {
+ if (!isWritable()) {
+ throw new IllegalStateException(
+ "This CSV DataContext is not writable, as it based on a read-only resource.");
+ }
+ }
+
+ @Override
+ public void executeUpdate(UpdateScript update) {
+ checkWritable();
+ CsvUpdateCallback callback = new CsvUpdateCallback(this);
+ synchronized (WRITE_LOCK) {
+ try {
+ update.run(callback);
+ } finally {
+ callback.close();
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvDataSet.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvDataSet.java b/csv/src/main/java/org/apache/metamodel/csv/CsvDataSet.java
new file mode 100644
index 0000000..ae31865
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvDataSet.java
@@ -0,0 +1,127 @@
+/**
+ * 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.csv;
+
+import java.io.IOException;
+
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.data.AbstractDataSet;
+import org.eobjects.metamodel.data.DefaultRow;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.util.FileHelper;
+
+import au.com.bytecode.opencsv.CSVReader;
+
+/**
+ * Streaming DataSet implementation for CSV support
+ *
+ * @author Kasper Sørensen
+ */
+final class CsvDataSet extends AbstractDataSet {
+
+ private final CSVReader _reader;
+ private final boolean _failOnInconsistentRowLength;
+ private final int _columnsInTable;
+ private volatile int _rowNumber;
+ private volatile Integer _rowsRemaining;
+ private volatile Row _row;
+
+ public CsvDataSet(CSVReader reader, Column[] columns, Integer maxRows,
+ int columnsInTable, boolean failOnInconsistentRowLength) {
+ super(columns);
+ _reader = reader;
+ _columnsInTable = columnsInTable;
+ _failOnInconsistentRowLength = failOnInconsistentRowLength;
+ _rowNumber = 0;
+ _rowsRemaining = maxRows;
+ }
+
+ @Override
+ public void close() {
+ FileHelper.safeClose(_reader);
+ _row = null;
+ _rowsRemaining = null;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ // close is always safe to invoke
+ close();
+ }
+
+ @Override
+ public Row getRow() throws MetaModelException {
+ return _row;
+ }
+
+ @Override
+ public boolean next() {
+ if (_rowsRemaining != null && _rowsRemaining > 0) {
+ _rowsRemaining--;
+ return nextInternal();
+ } else if (_rowsRemaining == null) {
+ return nextInternal();
+ } else {
+ return false;
+ }
+ }
+
+ private boolean nextInternal() {
+ if (_reader == null) {
+ return false;
+ }
+ final String[] csvValues;
+ try {
+ csvValues = _reader.readNext();
+ } catch (IOException e) {
+ throw new IllegalStateException("Exception reading from file", e);
+ }
+ if (csvValues == null) {
+ close();
+ return false;
+ }
+
+ final int size = getHeader().size();
+ final Object[] rowValues = new Object[size];
+ for (int i = 0; i < size; i++) {
+ Column column = getHeader().getSelectItem(i).getColumn();
+ int columnNumber = column.getColumnNumber();
+ if (columnNumber < csvValues.length) {
+ rowValues[i] = csvValues[columnNumber];
+ } else {
+ // Ticket #125: Missing values should be enterpreted as
+ // null.
+ rowValues[i] = null;
+ }
+ }
+ _row = new DefaultRow(getHeader(), rowValues);
+
+ if (_failOnInconsistentRowLength) {
+ _rowNumber++;
+ if (_columnsInTable != csvValues.length) {
+ throw new InconsistentRowLengthException(_columnsInTable, _row,
+ csvValues, _rowNumber);
+ }
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvDeleteBuilder.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvDeleteBuilder.java b/csv/src/main/java/org/apache/metamodel/csv/CsvDeleteBuilder.java
new file mode 100644
index 0000000..52c18e0
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvDeleteBuilder.java
@@ -0,0 +1,103 @@
+/**
+ * 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.csv;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.UpdateCallback;
+import org.eobjects.metamodel.UpdateScript;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.delete.AbstractRowDeletionBuilder;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.Action;
+import org.eobjects.metamodel.util.FileHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class CsvDeleteBuilder extends AbstractRowDeletionBuilder {
+
+ private static final Logger logger = LoggerFactory.getLogger(CsvDeleteBuilder.class);
+
+ private final CsvUpdateCallback _updateCallback;
+
+ public CsvDeleteBuilder(CsvUpdateCallback updateCallback, Table table) {
+ super(table);
+ _updateCallback = updateCallback;
+ }
+
+ @Override
+ public void execute() throws MetaModelException {
+ final File tempFile = FileHelper.createTempFile("metamodel_deletion", "csv");
+
+ final CsvConfiguration configuration = _updateCallback.getConfiguration();
+
+ final CsvDataContext copyDataContext = new CsvDataContext(tempFile, configuration);
+ copyDataContext.executeUpdate(new UpdateScript() {
+
+ @Override
+ public void run(UpdateCallback callback) {
+ final Table originalTable = getTable();
+ final Table copyTable = callback.createTable(copyDataContext.getDefaultSchema(), originalTable.getName())
+ .like(originalTable).execute();
+
+ if (isTruncateTableOperation()) {
+ // no need to iterate old records, they should all be
+ // removed
+ return;
+ }
+
+ final DataSet dataSet = _updateCallback.getDataContext().query().from(originalTable)
+ .select(originalTable.getColumns()).execute();
+ try {
+ while (dataSet.next()) {
+ final Row row = dataSet.getRow();
+ if (!deleteRow(row)) {
+ callback.insertInto(copyTable).like(row).execute();
+ }
+ }
+ } finally {
+ dataSet.close();
+ }
+ }
+ });
+
+ // copy the copy (which does not have deleted records) to overwrite the
+ // original
+ final InputStream in = FileHelper.getInputStream(tempFile);
+ try {
+ _updateCallback.getResource().write(new Action<OutputStream>() {
+ @Override
+ public void run(OutputStream out) throws Exception {
+ FileHelper.copy(in, out);
+ }
+ });
+ } finally {
+ FileHelper.safeClose(in);
+ }
+
+ final boolean deleted = tempFile.delete();
+ if (!deleted) {
+ logger.warn("Could not delete temporary copy-file: {}", tempFile);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvInsertBuilder.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvInsertBuilder.java b/csv/src/main/java/org/apache/metamodel/csv/CsvInsertBuilder.java
new file mode 100644
index 0000000..718de8e
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvInsertBuilder.java
@@ -0,0 +1,40 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.insert.AbstractRowInsertionBuilder;
+import org.eobjects.metamodel.schema.Table;
+
+final class CsvInsertBuilder extends AbstractRowInsertionBuilder<CsvUpdateCallback> {
+
+ public CsvInsertBuilder(CsvUpdateCallback updateCallback, Table table) {
+ super(updateCallback, table);
+ }
+
+ @Override
+ public void execute() {
+ Object[] values = getValues();
+ String[] stringValues = new String[values.length];
+ for (int i = 0; i < stringValues.length; i++) {
+ stringValues[i] = values[i] == null ? "" : values[i].toString();
+ }
+ getUpdateCallback().writeRow(stringValues, true);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvSchema.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvSchema.java b/csv/src/main/java/org/apache/metamodel/csv/CsvSchema.java
new file mode 100644
index 0000000..c6d2ba9
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvSchema.java
@@ -0,0 +1,63 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.schema.AbstractSchema;
+import org.eobjects.metamodel.schema.Table;
+
+final class CsvSchema extends AbstractSchema {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String _name;
+ private final transient CsvDataContext _dataContext;
+ private CsvTable _table;
+
+ public CsvSchema(String name, CsvDataContext dataContext) {
+ super();
+ _name = name;
+ _dataContext = dataContext;
+ }
+
+ protected void setTable(CsvTable table) {
+ _table = table;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ protected CsvDataContext getDataContext() {
+ return _dataContext;
+ }
+
+ @Override
+ public String getQuote() {
+ return null;
+ }
+
+ @Override
+ public Table[] getTables() {
+ if (_table == null) {
+ return new Table[0];
+ }
+ return new Table[] { _table };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvTable.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvTable.java b/csv/src/main/java/org/apache/metamodel/csv/CsvTable.java
new file mode 100644
index 0000000..eb9bdc0
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvTable.java
@@ -0,0 +1,149 @@
+/**
+ * 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.csv;
+
+import java.io.IOException;
+
+import org.eobjects.metamodel.schema.AbstractTable;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.Relationship;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.TableType;
+import org.eobjects.metamodel.util.AlphabeticSequence;
+import org.eobjects.metamodel.util.FileHelper;
+
+import au.com.bytecode.opencsv.CSVReader;
+
+final class CsvTable extends AbstractTable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final CsvSchema _schema;
+ private Column[] _columns;
+
+ /**
+ * Constructor for creating a new CSV table which has not yet been written.
+ *
+ * @param schema
+ * @param columnNames
+ */
+ public CsvTable(CsvSchema schema, String[] columnNames) {
+ this(schema);
+ _columns = buildColumns(columnNames);
+ }
+
+ /**
+ * Constructor for reading an existing CSV table.
+ *
+ * @param schema
+ */
+ public CsvTable(CsvSchema schema) {
+ _schema = schema;
+ }
+
+ @Override
+ public String getName() {
+ String schemaName = _schema.getName();
+ return schemaName.substring(0, schemaName.length() - 4);
+ }
+
+ @Override
+ public Column[] getColumns() {
+ if (_columns == null) {
+ synchronized (this) {
+ if (_columns == null) {
+ _columns = buildColumns();
+ }
+ }
+ }
+ return _columns;
+ }
+
+ private Column[] buildColumns() {
+ CSVReader reader = null;
+ try {
+ reader = _schema.getDataContext().createCsvReader(0);
+
+ final int columnNameLineNumber = _schema.getDataContext().getConfiguration().getColumnNameLineNumber();
+ for (int i = 1; i < columnNameLineNumber; i++) {
+ reader.readNext();
+ }
+ final String[] columnHeaders = reader.readNext();
+
+ reader.close();
+ return buildColumns(columnHeaders);
+ } catch (IOException e) {
+ throw new IllegalStateException("Exception reading from resource: " + _schema.getDataContext().getResource().getName(), e);
+ } finally {
+ FileHelper.safeClose(reader);
+ }
+ }
+
+ private Column[] buildColumns(final String[] columnNames) {
+ if (columnNames == null) {
+ return new Column[0];
+ }
+
+ final CsvConfiguration configuration = _schema.getDataContext().getConfiguration();
+ final int columnNameLineNumber = configuration.getColumnNameLineNumber();
+ final boolean nullable = !configuration.isFailOnInconsistentRowLength();
+
+ final Column[] columns = new Column[columnNames.length];
+ final AlphabeticSequence sequence = new AlphabeticSequence();
+ for (int i = 0; i < columnNames.length; i++) {
+ final String columnName;
+ if (columnNameLineNumber == CsvConfiguration.NO_COLUMN_NAME_LINE) {
+ columnName = sequence.next();
+ } else {
+ columnName = columnNames[i];
+ }
+ Column column = new MutableColumn(columnName, ColumnType.VARCHAR, this, i, null, null, nullable, null,
+ false, null);
+ columns[i] = column;
+ }
+ return columns;
+ }
+
+ @Override
+ public Schema getSchema() {
+ return _schema;
+ }
+
+ @Override
+ public TableType getType() {
+ return TableType.TABLE;
+ }
+
+ @Override
+ public Relationship[] getRelationships() {
+ return new Relationship[0];
+ }
+
+ @Override
+ public String getRemarks() {
+ return null;
+ }
+
+ @Override
+ public String getQuote() {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvTableDropBuilder.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvTableDropBuilder.java b/csv/src/main/java/org/apache/metamodel/csv/CsvTableDropBuilder.java
new file mode 100644
index 0000000..0685fb4
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvTableDropBuilder.java
@@ -0,0 +1,38 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.drop.AbstractTableDropBuilder;
+import org.eobjects.metamodel.schema.Table;
+
+final class CsvTableDropBuilder extends AbstractTableDropBuilder {
+
+ private final CsvUpdateCallback _updateCallback;
+
+ public CsvTableDropBuilder(CsvUpdateCallback updateCallback, Table table) {
+ super(table);
+ _updateCallback = updateCallback;
+ }
+
+ @Override
+ public void execute() {
+ _updateCallback.dropTable();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvUpdateCallback.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvUpdateCallback.java b/csv/src/main/java/org/apache/metamodel/csv/CsvUpdateCallback.java
new file mode 100644
index 0000000..72e276c
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvUpdateCallback.java
@@ -0,0 +1,249 @@
+/**
+ * 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.csv;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.RandomAccessFile;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+
+import org.eobjects.metamodel.AbstractUpdateCallback;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.UpdateCallback;
+import org.eobjects.metamodel.create.TableCreationBuilder;
+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;
+import org.eobjects.metamodel.update.RowUpdationBuilder;
+import org.eobjects.metamodel.util.Action;
+import org.eobjects.metamodel.util.EqualsBuilder;
+import org.eobjects.metamodel.util.FileHelper;
+import org.eobjects.metamodel.util.FileResource;
+import org.eobjects.metamodel.util.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class CsvUpdateCallback extends AbstractUpdateCallback implements UpdateCallback {
+
+ private static final Logger logger = LoggerFactory.getLogger(CsvUpdateCallback.class);
+
+ private final CsvConfiguration _configuration;
+ private final Resource _resource;
+ private Writer _writer;
+
+ public CsvUpdateCallback(CsvDataContext dataContext) {
+ super(dataContext);
+ _resource = dataContext.getResource();
+ _configuration = dataContext.getConfiguration();
+ }
+
+ @Override
+ public TableCreationBuilder createTable(Schema schema, String name) throws IllegalArgumentException, IllegalStateException {
+ return new CsvCreateTableBuilder(this, schema, name);
+ }
+
+ @Override
+ public RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException {
+ validateTable(table);
+ return new CsvInsertBuilder(this, table);
+ }
+
+ public CsvConfiguration getConfiguration() {
+ return _configuration;
+ }
+
+ public Resource getResource() {
+ return _resource;
+ }
+
+ private void validateTable(Table table) {
+ if (!(table instanceof CsvTable)) {
+ throw new IllegalArgumentException("Not a valid CSV table: " + table);
+ }
+ }
+
+ protected synchronized void writeRow(final String[] stringValues, final boolean append) {
+ final CsvWriter _csvWriter = new CsvWriter(_configuration);
+ final String line = _csvWriter.buildLine(stringValues);
+ if (_resource instanceof FileResource) {
+ // optimized handling for file-based resources
+ final File file = ((FileResource) _resource).getFile();
+ final Writer writer = getFileWriter(file, append);
+ try {
+ writer.write(line);
+ } catch (IOException e) {
+ throw new MetaModelException("Failed to write line to file: " + line, e);
+ }
+ } else {
+ // generic handling for any kind of resource
+ final Action<OutputStream> action = new Action<OutputStream>() {
+ @Override
+ public void run(OutputStream out) throws Exception {
+ final String encoding = _configuration.getEncoding();
+ final OutputStreamWriter writer = new OutputStreamWriter(out, encoding);
+ writer.write(line);
+ writer.flush();
+ }
+ };
+ if (append) {
+ _resource.append(action);
+ } else {
+ _resource.write(action);
+ }
+ }
+ }
+
+ private Writer getFileWriter(File file, boolean append) {
+ if (_writer == null || !append) {
+ final boolean needsLineBreak = needsLineBreak(file, _configuration);
+
+ final Writer writer = FileHelper.getWriter(file, _configuration.getEncoding(), append);
+ if (needsLineBreak) {
+ try {
+ writer.write('\n');
+ } catch (IOException e) {
+ logger.debug("Failed to insert newline", e);
+ }
+ }
+ _writer = writer;
+ }
+ return _writer;
+ }
+
+ protected static boolean needsLineBreak(File file, CsvConfiguration configuration) {
+ if (!file.exists() || file.length() == 0) {
+ return false;
+ }
+
+ try {
+ // find the bytes a newline would match under the encoding
+ final byte[] bytesInLineBreak;
+ {
+ ByteBuffer encodedLineBreak = Charset.forName(configuration.getEncoding()).encode("\n");
+ bytesInLineBreak = new byte[encodedLineBreak.capacity()];
+ encodedLineBreak.get(bytesInLineBreak);
+ }
+
+ // find the last bytes of the file
+ final byte[] bytesFromFile = new byte[bytesInLineBreak.length];
+ {
+ final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
+ try {
+ FileChannel channel = randomAccessFile.getChannel();
+ try {
+ long length = randomAccessFile.length();
+
+ channel = channel.position(length - bytesInLineBreak.length);
+ channel.read(ByteBuffer.wrap(bytesFromFile));
+ } finally {
+ channel.close();
+ }
+ } finally {
+ randomAccessFile.close();
+ }
+ }
+
+ // if the two byte arrays match, then the newline is not needed.
+ if (EqualsBuilder.equals(bytesInLineBreak, bytesFromFile)) {
+ return false;
+ }
+ return true;
+ } catch (Exception e) {
+ logger.error("Error occurred while checking if file needs linebreak, omitting check", e);
+ }
+ return false;
+ }
+
+ /**
+ * Closes all open handles
+ */
+ protected void close() {
+ if (_writer != null) {
+ try {
+ _writer.flush();
+ } catch (IOException e) {
+ logger.warn("Failed to flush CSV writer", e);
+ }
+ try {
+ _writer.close();
+ } catch (IOException e) {
+ logger.error("Failed to close CSV writer", e);
+ } finally {
+ _writer = null;
+ }
+ }
+ }
+
+ @Override
+ public RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException {
+ close();
+ return super.update(table);
+ }
+
+ @Override
+ public boolean isDropTableSupported() {
+ return true;
+ }
+
+ @Override
+ public TableDropBuilder dropTable(Table table) {
+ validateTable(table);
+ return new CsvTableDropBuilder(this, table);
+ }
+
+ /**
+ * Callback method used by {@link CsvTableDropBuilder} when execute is
+ * called
+ */
+ protected void dropTable() {
+ close();
+ if (_resource instanceof FileResource) {
+ final File file = ((FileResource) _resource).getFile();
+ final boolean success = file.delete();
+ if (!success) {
+ throw new MetaModelException("Could not delete (drop) file: " + file);
+ }
+ } else {
+ _resource.write(new Action<OutputStream>() {
+ @Override
+ public void run(OutputStream arg) throws Exception {
+ // do nothing, just write an empty file
+ }
+ });
+ }
+ }
+
+ @Override
+ public boolean isDeleteSupported() {
+ return true;
+ }
+
+ @Override
+ public RowDeletionBuilder deleteFrom(Table table) {
+ validateTable(table);
+ return new CsvDeleteBuilder(this, table);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/CsvWriter.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvWriter.java b/csv/src/main/java/org/apache/metamodel/csv/CsvWriter.java
new file mode 100644
index 0000000..7b35847
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/CsvWriter.java
@@ -0,0 +1,94 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.util.Resource;
+
+/**
+ * This class is an adaptation of the CSVWriter class of OpenCSV. We've made the
+ * writer work without having the output stream as state (suiting for
+ * {@link Resource} usage).
+ */
+public final class CsvWriter {
+
+ public static final int INITIAL_STRING_SIZE = 128;
+
+ private final CsvConfiguration _configuration;
+
+ public CsvWriter(CsvConfiguration configuration) {
+ _configuration = configuration;
+ }
+
+ /**
+ * Builds a line for the CSV file output
+ *
+ * @param nextLine
+ * a string array with each comma-separated element as a separate
+ * entry.
+ */
+ public String buildLine(String[] nextLine) {
+ final StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE);
+ for (int i = 0; i < nextLine.length; i++) {
+
+ if (i != 0) {
+ sb.append(_configuration.getSeparatorChar());
+ }
+
+ final String nextElement = nextLine[i];
+ if (nextElement == null) {
+ continue;
+ }
+ final char quoteChar = _configuration.getQuoteChar();
+ if (quoteChar != CsvConfiguration.NOT_A_CHAR) {
+ sb.append(quoteChar);
+ }
+
+ sb.append(stringContainsSpecialCharacters(nextElement) ? processLine(nextElement) : nextElement);
+
+ if (quoteChar != CsvConfiguration.NOT_A_CHAR) {
+ sb.append(quoteChar);
+ }
+ }
+
+ sb.append('\n');
+ return sb.toString();
+
+ }
+
+ private boolean stringContainsSpecialCharacters(String line) {
+ return line.indexOf(_configuration.getQuoteChar()) != -1 || line.indexOf(_configuration.getEscapeChar()) != -1;
+ }
+
+ private StringBuilder processLine(String nextElement) {
+ final StringBuilder sb = new StringBuilder(INITIAL_STRING_SIZE);
+ for (int j = 0; j < nextElement.length(); j++) {
+ final char nextChar = nextElement.charAt(j);
+ final char escapeChar = _configuration.getEscapeChar();
+ if (escapeChar != CsvConfiguration.NOT_A_CHAR && nextChar == _configuration.getQuoteChar()) {
+ sb.append(escapeChar).append(nextChar);
+ } else if (escapeChar != CsvConfiguration.NOT_A_CHAR && nextChar == escapeChar) {
+ sb.append(escapeChar).append(nextChar);
+ } else {
+ sb.append(nextChar);
+ }
+ }
+
+ return sb;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/InconsistentRowLengthException.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/InconsistentRowLengthException.java b/csv/src/main/java/org/apache/metamodel/csv/InconsistentRowLengthException.java
new file mode 100644
index 0000000..60c093f
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/InconsistentRowLengthException.java
@@ -0,0 +1,101 @@
+/**
+ * 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.csv;
+
+import org.eobjects.metamodel.InconsistentRowFormatException;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.Row;
+
+/**
+ * Exception thrown when a line in a CSV file has an inconsistent amount of
+ * columns compared to the previous lines (and headers). The exception will be
+ * thrown when {@link DataSet#next()} is called.
+ *
+ * Note that this exception is only thrown if the
+ * {@link CsvConfiguration#isFailOnInconsistentRowLength()} property is true.
+ * Enabling it allows a somewhat different approach to iterating through a
+ * resulting DataSet. For example something like:
+ *
+ * <pre>
+ * while (true) {
+ * try {
+ * if (!dataSet.next) {
+ * break;
+ * }
+ * Row row = dataSet.getRow();
+ * handleRegularRow(row);
+ * } catch (InconsistentRowLengthException e) {
+ * handleIrregularRow(e.getSourceLine());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Kasper Sørensen
+ */
+public final class InconsistentRowLengthException extends
+ InconsistentRowFormatException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final int _columnsInTable;
+ private final String[] _line;
+
+ public InconsistentRowLengthException(int columnsInTable, Row proposedRow,
+ String[] line, int rowNumber) {
+ super(proposedRow, rowNumber);
+ _columnsInTable = columnsInTable;
+ _line = line;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Inconsistent length of row no. " + getRowNumber()
+ + ". Expected " + getColumnsInTable() + " columns but found "
+ + getColumnsInLine() + ".";
+ }
+
+ /**
+ * Gets the source line, as parsed by the CSV parser (regardless of table
+ * metadata).
+ *
+ * @return an array of string values.
+ */
+ public String[] getSourceLine() {
+ return _line;
+ }
+
+ /**
+ * Gets the amount of columns in the parsed line.
+ *
+ * @return an int representing the amount of values in the inconsistent
+ * line.
+ */
+ public int getColumnsInLine() {
+ return _line.length;
+ }
+
+ /**
+ * Gets the expected amounts of columns, as defined by the table metadata.
+ *
+ * @return an int representing the amount of columns defined in the table.
+ */
+ public int getColumnsInTable() {
+ return _columnsInTable;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/apache/metamodel/csv/package-info.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/apache/metamodel/csv/package-info.java b/csv/src/main/java/org/apache/metamodel/csv/package-info.java
new file mode 100644
index 0000000..241c74e
--- /dev/null
+++ b/csv/src/main/java/org/apache/metamodel/csv/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 Comma Separated Values (CSV) files
+ */
+package org.eobjects.metamodel.csv;
+
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/eobjects/metamodel/csv/CsvConfiguration.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/eobjects/metamodel/csv/CsvConfiguration.java b/csv/src/main/java/org/eobjects/metamodel/csv/CsvConfiguration.java
deleted file mode 100644
index c67615b..0000000
--- a/csv/src/main/java/org/eobjects/metamodel/csv/CsvConfiguration.java
+++ /dev/null
@@ -1,160 +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.csv;
-
-import java.io.Serializable;
-import java.util.List;
-
-import org.eobjects.metamodel.util.BaseObject;
-import org.eobjects.metamodel.util.FileHelper;
-
-/**
- * Represents the configuration for reading/parsing CSV files.
- *
- * @author Kasper Sørensen
- */
-public final class CsvConfiguration extends BaseObject implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * The value is '\\uFFFF', the "not a character" value which should not
- * occur in any valid Unicode string. This special char can be used to
- * disable either quote chars or escape chars.
- */
- public static final char NOT_A_CHAR = '\uFFFF';
- public static final int NO_COLUMN_NAME_LINE = 0;
- public static final int DEFAULT_COLUMN_NAME_LINE = 1;
- public static final char DEFAULT_SEPARATOR_CHAR = ',';
- public static final char DEFAULT_QUOTE_CHAR = '"';
- public static final char DEFAULT_ESCAPE_CHAR = '\\';
-
- private final int columnNameLineNumber;
- private final String encoding;
- private final char separatorChar;
- private final char quoteChar;
- private final char escapeChar;
- private final boolean failOnInconsistentRowLength;
-
- public CsvConfiguration() {
- this(DEFAULT_COLUMN_NAME_LINE);
- }
-
- public CsvConfiguration(int columnNameLineNumber) {
- this(columnNameLineNumber, FileHelper.DEFAULT_ENCODING,
- DEFAULT_SEPARATOR_CHAR, DEFAULT_QUOTE_CHAR, DEFAULT_ESCAPE_CHAR);
- }
-
- public CsvConfiguration(int columnNameLineNumber, String encoding,
- char separatorChar, char quoteChar, char escapeChar) {
- this(columnNameLineNumber, encoding, separatorChar, quoteChar,
- escapeChar, false);
- }
-
- public CsvConfiguration(int columnNameLineNumber, String encoding,
- char separatorChar, char quoteChar, char escapeChar,
- boolean failOnInconsistentRowLength) {
- this.columnNameLineNumber = columnNameLineNumber;
- this.encoding = encoding;
- this.separatorChar = separatorChar;
- this.quoteChar = quoteChar;
- this.escapeChar = escapeChar;
- this.failOnInconsistentRowLength = failOnInconsistentRowLength;
- }
-
- /**
- * Determines whether to fail (by throwing an
- * {@link InconsistentRowLengthException}) if a line in the CSV file has
- * inconsistent amounts of columns.
- *
- * If set to false (default) MetaModel will gracefully fill in missing null
- * values in or ignore additional values in a line.
- *
- * @return a boolean indicating whether to fail or gracefully compensate for
- * inconsistent lines in the CSV files.
- */
- public boolean isFailOnInconsistentRowLength() {
- return failOnInconsistentRowLength;
- }
-
- /**
- * The line number (1 based) from which to get the names of the columns.
- *
- * @return the line number (1 based)
- */
- public int getColumnNameLineNumber() {
- return columnNameLineNumber;
- }
-
- /**
- * Gets the file encoding to use for reading the file.
- *
- * @return the text encoding of the file.
- */
- public String getEncoding() {
- return encoding;
- }
-
- /**
- * Gets the separator char (typically comma or semicolon) for separating
- * values.
- *
- * @return the separator char
- */
- public char getSeparatorChar() {
- return separatorChar;
- }
-
- /**
- * Gets the quote char, used for encapsulating values.
- *
- * @return the quote char
- */
- public char getQuoteChar() {
- return quoteChar;
- }
-
- /**
- * Gets the escape char, used for escaping eg. quote chars inside values.
- *
- * @return the escape char
- */
- public char getEscapeChar() {
- return escapeChar;
- }
-
- @Override
- protected void decorateIdentity(List<Object> identifiers) {
- identifiers.add(columnNameLineNumber);
- identifiers.add(encoding);
- identifiers.add(separatorChar);
- identifiers.add(quoteChar);
- identifiers.add(escapeChar);
- identifiers.add(failOnInconsistentRowLength);
- }
-
- @Override
- public String toString() {
- return "CsvConfiguration[columnNameLineNumber=" + columnNameLineNumber
- + ", encoding=" + encoding + ", separatorChar=" + separatorChar
- + ", quoteChar=" + quoteChar + ", escapeChar=" + escapeChar
- + ", failOnInconsistentRowLength="
- + failOnInconsistentRowLength + "]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/csv/src/main/java/org/eobjects/metamodel/csv/CsvCreateTableBuilder.java
----------------------------------------------------------------------
diff --git a/csv/src/main/java/org/eobjects/metamodel/csv/CsvCreateTableBuilder.java b/csv/src/main/java/org/eobjects/metamodel/csv/CsvCreateTableBuilder.java
deleted file mode 100644
index 30e0a54..0000000
--- a/csv/src/main/java/org/eobjects/metamodel/csv/CsvCreateTableBuilder.java
+++ /dev/null
@@ -1,51 +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.csv;
-
-import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
-import org.eobjects.metamodel.schema.MutableTable;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-
-final class CsvCreateTableBuilder extends
- AbstractTableCreationBuilder<CsvUpdateCallback> {
-
- public CsvCreateTableBuilder(CsvUpdateCallback updateCallback,
- Schema schema, String name) {
- super(updateCallback, schema, name);
- if (!(schema instanceof CsvSchema)) {
- throw new IllegalArgumentException("Not a valid CSV schema: "
- + schema);
- }
- }
-
- @Override
- public Table execute() {
- CsvUpdateCallback csvUpdateCallback = getUpdateCallback();
-
- MutableTable table = getTable();
- String[] columnNames = table.getColumnNames();
- csvUpdateCallback.writeRow(columnNames, false);
-
- CsvSchema schema = (CsvSchema) table.getSchema();
- CsvTable csvTable = new CsvTable(schema, table.getColumnNames());
- schema.setTable(csvTable);
- return csvTable;
- }
-}