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 2014/07/20 08:03:28 UTC

[2/5] git commit: METAMODEL-69: Applied patch from review board.

METAMODEL-69: Applied patch from review board.

Project: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/commit/cad631d6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/tree/cad631d6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/diff/cad631d6

Branch: refs/heads/master
Commit: cad631d6b8b8fd0a57409356c756e4f448b8851f
Parents: 9d60bce
Author: Kasper Sørensen <i....@gmail.com>
Authored: Sat Jul 19 21:27:37 2014 +0200
Committer: Kasper Sørensen <i....@gmail.com>
Committed: Sat Jul 19 21:27:37 2014 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../org/apache/metamodel/schema/JdbcTypes.java  |   2 +-
 .../LegacyDeserializationObjectInputStream.java | 218 ++++++++++++++++++-
 .../apache/metamodel/data/DefaultRowTest.java   |  15 +-
 ...acyDeserializationObjectInputStreamTest.java |  83 +++++++
 5 files changed, 313 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/cad631d6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 3c4e0fa..57b7b4f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -14,6 +14,7 @@ Apache MetaModel 4.2.0-incubating
  * [METAMODEL-62] - Fixed a bug related to fault-tolerant handling of malformed CSV lines when reading CSVs in single-line mode
  * [METAMODEL-68] - Made it possible to create a CSV table without a header line in the file, if the user configures it.
  * [METAMODEL-67] - Upgraded Jackson (JSON library) dependency from org.codehaus namespace to the newer com.fasterxml namespace.
+ * [METAMODEL-69] - Fixed issue with deserialization of ColumnType into the new interface instead of the old enum.
 
 Apache MetaModel 4.1.0-incubating
 

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/cad631d6/core/src/main/java/org/apache/metamodel/schema/JdbcTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/schema/JdbcTypes.java b/core/src/main/java/org/apache/metamodel/schema/JdbcTypes.java
index 2ab39ab..a76b9c6 100644
--- a/core/src/main/java/org/apache/metamodel/schema/JdbcTypes.java
+++ b/core/src/main/java/org/apache/metamodel/schema/JdbcTypes.java
@@ -24,7 +24,7 @@ package org.apache.metamodel.schema;
  * additional types (confirmed by JavaTypesTest). It is being used to convert
  * JDBC types to ColumnType enumerations.
  */
-final class JdbcTypes {
+public final class JdbcTypes {
 
 	// Prevent instantiation
 	private JdbcTypes() {

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/cad631d6/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java b/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java
index c5ab2e5..3e492b8 100644
--- a/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java
+++ b/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java
@@ -18,10 +18,30 @@
  */
 package org.apache.metamodel.util;
 
+import static org.apache.metamodel.schema.SuperColumnType.BINARY_TYPE;
+import static org.apache.metamodel.schema.SuperColumnType.BOOLEAN_TYPE;
+import static org.apache.metamodel.schema.SuperColumnType.LITERAL_TYPE;
+import static org.apache.metamodel.schema.SuperColumnType.NUMBER_TYPE;
+import static org.apache.metamodel.schema.SuperColumnType.OTHER_TYPE;
+import static org.apache.metamodel.schema.SuperColumnType.TIME_TYPE;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamClass;
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Types;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.schema.JdbcTypes;
+import org.apache.metamodel.schema.SuperColumnType;
 
 /**
  * A specialized {@link ObjectInputStream} for MetaModel which can be used or
@@ -31,17 +51,211 @@ import java.io.ObjectStreamClass;
  */
 public class LegacyDeserializationObjectInputStream extends ObjectInputStream {
 
+    /**
+     * Implementation of the new {@link ColumnType} interface which still
+     * adheres to the constant/enum values of the old ColumnType definition.
+     * While deserializing old ColumnType objects, we will convert them to this
+     * enum.
+     */
+    protected static enum LegacyColumnType implements ColumnType {
+
+        /**
+         * Literal
+         */
+        CHAR(LITERAL_TYPE), VARCHAR(LITERAL_TYPE), LONGVARCHAR(LITERAL_TYPE), CLOB(LITERAL_TYPE), NCHAR(LITERAL_TYPE), NVARCHAR(
+                LITERAL_TYPE), LONGNVARCHAR(LITERAL_TYPE), NCLOB(LITERAL_TYPE),
+
+        /**
+         * Numbers
+         */
+        TINYINT(NUMBER_TYPE), SMALLINT(NUMBER_TYPE), INTEGER(NUMBER_TYPE), BIGINT(NUMBER_TYPE), FLOAT(NUMBER_TYPE), REAL(
+                NUMBER_TYPE), DOUBLE(NUMBER_TYPE), NUMERIC(NUMBER_TYPE), DECIMAL(NUMBER_TYPE),
+
+        /**
+         * Time based
+         */
+        DATE(TIME_TYPE), TIME(TIME_TYPE), TIMESTAMP(TIME_TYPE),
+
+        /**
+         * Booleans
+         */
+        BIT(BOOLEAN_TYPE), BOOLEAN(BOOLEAN_TYPE),
+
+        /**
+         * Binary types
+         */
+        BINARY(BINARY_TYPE), VARBINARY(BINARY_TYPE), LONGVARBINARY(BINARY_TYPE), BLOB(BINARY_TYPE),
+
+        /**
+         * Other types (as defined in {@link Types}).
+         */
+        NULL(OTHER_TYPE), OTHER(OTHER_TYPE), JAVA_OBJECT(OTHER_TYPE), DISTINCT(OTHER_TYPE), STRUCT(OTHER_TYPE), ARRAY(
+                OTHER_TYPE), REF(OTHER_TYPE), DATALINK(OTHER_TYPE), ROWID(OTHER_TYPE), SQLXML(OTHER_TYPE),
+
+        /**
+         * Additional types (added by MetaModel for non-JDBC datastores)
+         */
+        LIST(OTHER_TYPE), MAP(OTHER_TYPE);
+
+        private final SuperColumnType _superType;
+
+        private LegacyColumnType(SuperColumnType superType) {
+            if (superType == null) {
+                throw new IllegalArgumentException("SuperColumnType cannot be null");
+            }
+            _superType = superType;
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+
+        @Override
+        public Comparator<Object> getComparator() {
+            if (isTimeBased()) {
+                return TimeComparator.getComparator();
+            }
+            if (isNumber()) {
+                return NumberComparator.getComparator();
+            }
+            if (isLiteral()) {
+                return ToStringComparator.getComparator();
+            }
+            return ObjectComparator.getComparator();
+        }
+
+        @Override
+        public boolean isBoolean() {
+            return _superType == BOOLEAN_TYPE;
+        }
+
+        @Override
+        public boolean isBinary() {
+            return _superType == BINARY_TYPE;
+        }
+
+        @Override
+        public boolean isNumber() {
+            return _superType == NUMBER_TYPE;
+        }
+
+        @Override
+        public boolean isTimeBased() {
+            return _superType == TIME_TYPE;
+        }
+
+        @Override
+        public boolean isLiteral() {
+            return _superType == LITERAL_TYPE;
+        }
+
+        @Override
+        public boolean isLargeObject() {
+            switch (this) {
+            case BLOB:
+            case CLOB:
+            case NCLOB:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        @Override
+        public Class<?> getJavaEquivalentClass() {
+            switch (this) {
+            case TINYINT:
+            case SMALLINT:
+                return Short.class;
+            case INTEGER:
+                return Integer.class;
+            case BIGINT:
+                return BigInteger.class;
+            case DECIMAL:
+            case NUMERIC:
+            case FLOAT:
+            case REAL:
+            case DOUBLE:
+                return Double.class;
+            case DATE:
+            case TIME:
+            case TIMESTAMP:
+                return Date.class;
+            case BLOB:
+                return Blob.class;
+            case CLOB:
+            case NCLOB:
+                return Clob.class;
+            case MAP:
+                return Map.class;
+            case LIST:
+                return List.class;
+            default:
+                // All other types have fitting java equivalent classes in the
+                // super
+                // type
+                return _superType.getJavaEquivalentClass();
+            }
+        }
+
+        @Override
+        public SuperColumnType getSuperType() {
+            return _superType;
+        }
+
+        @Override
+        public int getJdbcType() throws IllegalStateException {
+            final String name = this.toString();
+            try {
+                // We assume that the JdbcTypes class only consists of constant
+                // integer types, so we make no assertions here
+                final Field[] fields = JdbcTypes.class.getFields();
+                for (int i = 0; i < fields.length; i++) {
+                    Field field = fields[i];
+                    String fieldName = field.getName();
+                    if (fieldName.equals(name)) {
+                        int value = (Integer) field.getInt(null);
+                        return value;
+                    }
+                }
+                throw new IllegalStateException("No JdbcType found with field name: " + name);
+            } catch (Exception e) {
+                throw new IllegalStateException("Could not access fields in JdbcTypes", e);
+            }
+        }
+    }
+
+    private static final String OLD_CLASS_NAME_COLUMN_TYPE = "org.eobjects.metamodel.schema.ColumnType";
+
     public LegacyDeserializationObjectInputStream(InputStream in) throws IOException, SecurityException {
         super(in);
     }
 
     @Override
     protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
-        String className = desc.getName();
+        final String className = desc.getName();
         if (className.startsWith("org.eobjects.metamodel") || className.startsWith("[Lorg.eobjects.metamodel")) {
-            String newClassName = className.replace("org.eobjects", "org.apache");
+            final String newClassName;
+            if (OLD_CLASS_NAME_COLUMN_TYPE.equals(className)) {
+                // since ColumnType was changed from enum to interface, there's
+                // some special treatment here.
+                newClassName = LegacyColumnType.class.getName();
+            } else {
+                newClassName = className.replace("org.eobjects", "org.apache");
+            }
             return Class.forName(newClassName);
         }
         return super.resolveClass(desc);
     }
+
+    @Override
+    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
+        final ObjectStreamClass objectStreamClass = super.readClassDescriptor();
+        if (OLD_CLASS_NAME_COLUMN_TYPE.equals(objectStreamClass.getName())) {
+            final ObjectStreamClass result = ObjectStreamClass.lookup(LegacyColumnType.class);
+            return result;
+        }
+        return objectStreamClass;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/cad631d6/core/src/test/java/org/apache/metamodel/data/DefaultRowTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/data/DefaultRowTest.java b/core/src/test/java/org/apache/metamodel/data/DefaultRowTest.java
index a3a45f6..40f0551 100644
--- a/core/src/test/java/org/apache/metamodel/data/DefaultRowTest.java
+++ b/core/src/test/java/org/apache/metamodel/data/DefaultRowTest.java
@@ -26,6 +26,8 @@ import java.io.ObjectOutputStream;
 import java.lang.reflect.Field;
 
 import org.apache.metamodel.query.SelectItem;
+import org.apache.metamodel.schema.Column;
+import org.apache.metamodel.schema.ColumnType;
 import org.apache.metamodel.schema.MutableColumn;
 import org.apache.metamodel.util.FileHelper;
 import org.apache.metamodel.util.LegacyDeserializationObjectInputStream;
@@ -37,18 +39,18 @@ public class DefaultRowTest extends TestCase {
     private SelectItem[] items = new SelectItem[] { new SelectItem(new MutableColumn("foo")),
             new SelectItem(new MutableColumn("bar")) };
     private Object[] values = new Object[] { "foo", "bar" };
-    
+
     public void testSerializeAndDeserialize() throws Exception {
         DefaultRow row = new DefaultRow(new SimpleDataSetHeader(items), values);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos);
         oos.writeObject(row);
         oos.close();
-        
+
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
         ObjectInputStream ois = new ObjectInputStream(bais);
         Object deserialized = ois.readObject();
-        
+
         assertEquals("Row[values=[foo, bar]]", deserialized.toString());
         assertEquals(row, deserialized);
     }
@@ -78,6 +80,13 @@ public class DefaultRowTest extends TestCase {
 
         assertEquals(Style.NO_STYLE, row.getStyle(0));
         assertEquals(Style.NO_STYLE, row.getStyle(1));
+
+        Column column = selectItems[0].getColumn();
+        assertNotNull(column);
+        
+        // the columns used to create the object did not have column types assigned.
+        ColumnType type = column.getType();
+        assertNull(type);
     }
 
     public void testGetValueOfColumn() throws Exception {

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/cad631d6/core/src/test/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStreamTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStreamTest.java b/core/src/test/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStreamTest.java
new file mode 100644
index 0000000..e202ad7
--- /dev/null
+++ b/core/src/test/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStreamTest.java
@@ -0,0 +1,83 @@
+/**
+ * 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.apache.metamodel.util;
+
+import java.io.FileInputStream;
+
+import org.apache.metamodel.query.Query;
+import org.apache.metamodel.schema.Column;
+import org.apache.metamodel.schema.Table;
+
+import junit.framework.TestCase;
+
+public class LegacyDeserializationObjectInputStreamTest extends TestCase {
+
+    /**
+     * Method initially used (with org.eobjects codebase) to generate the test
+     * input file:
+     * 
+     * <pre>
+     * public void testCreateOldSchema() throws Exception {
+     *     MutableSchema schema = new MutableSchema(&quot;myschema&quot;);
+     *     MutableTable table = new MutableTable(&quot;mytable&quot;, TableType.TABLE, schema);
+     *     schema.addTable(table);
+     * 
+     *     table.addColumn(new MutableColumn(&quot;mycol1&quot;, ColumnType.INTEGER, table, 0, 16, &quot;int&quot;, false, &quot;my remark 1&quot;, false,
+     *             &quot;\&quot;&quot;));
+     *     table.addColumn(new MutableColumn(&quot;mycol1&quot;, ColumnType.VARCHAR, table, 1, 255, &quot;text&quot;, true, &quot;my remark 2&quot;, true,
+     *             null));
+     * 
+     *     Query q = new Query();
+     *     q.from(table);
+     *     q.select(table.getColumn(0));
+     *     q.where(table.getColumn(1), OperatorType.EQUALS_TO, &quot;foo&quot;);
+     * 
+     *     FileOutputStream out = new FileOutputStream(&quot;src/test/resources/metamodel-3.4-query-and-schema.ser&quot;);
+     *     new ObjectOutputStream(out).writeObject(q);
+     *     out.close();
+     * }
+     * </pre>
+     */
+    public void testDeserializeOldQueryAndSchema() throws Exception {
+        final Object obj;
+        {
+            final FileInputStream in = new FileInputStream("src/test/resources/metamodel-3.4-query-and-schema.ser");
+            try {
+                final LegacyDeserializationObjectInputStream ois = new LegacyDeserializationObjectInputStream(in);
+                obj = ois.readObject();
+                ois.close();
+            } finally {
+                in.close();
+            }
+        }
+        
+        assertTrue(obj instanceof Query);
+        
+        final Query q = (Query) obj;
+        final Table table = q.getFromClause().getItem(0).getTable();
+        final Column[] columns = table.getColumns();
+
+        assertEquals("Table[name=mytable,type=TABLE,remarks=null]", table.toString());
+        assertEquals("Column[name=mycol1,columnNumber=0,type=INTEGER,nullable=false,nativeType=int,columnSize=16]", columns[0].toString());
+        assertEquals("Column[name=mycol1,columnNumber=1,type=VARCHAR,nullable=true,nativeType=text,columnSize=255]", columns[1].toString());
+        
+        assertEquals("SELECT mytable.\"mycol1\" FROM myschema.mytable WHERE mytable.mycol1 = 'foo'", q.toSql());
+    }
+
+}