]> source.dussan.org Git - iciql.git/commitdiff
Add support for runtime Mode in the DataTypeAdapters
authorJames Moger <james.moger@gitblit.com>
Mon, 10 Nov 2014 16:10:01 +0000 (11:10 -0500)
committerJames Moger <james.moger@gitblit.com>
Tue, 11 Nov 2014 02:46:37 +0000 (21:46 -0500)
12 files changed:
releases.moxie
src/main/java/com/iciql/Db.java
src/main/java/com/iciql/Iciql.java
src/main/java/com/iciql/SQLDialectDefault.java
src/main/java/com/iciql/adapter/GsonTypeAdapter.java
src/main/java/com/iciql/adapter/JavaSerializationTypeAdapter.java
src/main/java/com/iciql/adapter/SnakeYamlTypeAdapter.java
src/main/java/com/iciql/adapter/XStreamTypeAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonStringAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonbStringAdapter.java
src/main/java/com/iciql/adapter/postgresql/XmlStringAdapter.java
src/site/dta.mkd

index 6e271c77e63832d3688da885c3869b97a69cc777..b05ae9ca1ffd5544832c44ac2fad5ca680f8e706 100644 (file)
@@ -14,6 +14,7 @@ r23: {
     - Improved automatic date conversions
     - Revised data type adapters to be specified separately with the @TypeAdapter annotation
     additions:
+    - Add runtime mode support (DEV, TEST, & PROD)
     - Add a DAO feature similar to JDBI
     - Added Gson, XStream, and SnakeYaml type adapters
     dependencyChanges: ~
index 13c92602d437aa50c8e7fba4e5364f97c9a5ba2f..794417e4b50da5fcd62a9790f38f786f7133295c 100644 (file)
@@ -41,6 +41,7 @@ import com.iciql.DbUpgrader.DefaultDbUpgrader;
 import com.iciql.Iciql.IQTable;
 import com.iciql.Iciql.IQVersion;
 import com.iciql.Iciql.IQView;
+import com.iciql.Iciql.Mode;
 import com.iciql.util.IciqlLogger;
 import com.iciql.util.JdbcUtils;
 import com.iciql.util.StringUtils;
@@ -64,6 +65,7 @@ public class Db implements AutoCloseable {
        private static final Map<String, Class<? extends SQLDialect>> DIALECTS;
 
        private final Connection conn;
+       private final Mode mode;
        private final Map<Class<?>, TableDefinition<?>> classMap = Collections
                        .synchronizedMap(new HashMap<Class<?>, TableDefinition<?>>());
        private final SQLDialect dialect;
@@ -88,8 +90,9 @@ public class Db implements AutoCloseable {
            DIALECTS.put("SQLite", SQLDialectSQLite.class);
        }
 
-       private Db(Connection conn) {
+       private Db(Connection conn, Mode mode) {
                this.conn = conn;
+               this.mode = mode;
                String databaseName = null;
                try {
                        DatabaseMetaData data = conn.getMetaData();
@@ -148,50 +151,81 @@ public class Db implements AutoCloseable {
        }
 
        public static Db open(String url) {
+               return open(url, Mode.PROD);
+       }
+
+       public static Db open(String url, Mode mode) {
                try {
                        Connection conn = JdbcUtils.getConnection(null, url, null, null);
-                       return new Db(conn);
+                       return new Db(conn, mode);
                } catch (SQLException e) {
                        throw new IciqlException(e);
                }
        }
 
        public static Db open(String url, String user, String password) {
+               return open(url, user, password, Mode.PROD);
+       }
+
+       public static Db open(String url, String user, String password, Mode mode) {
                try {
                        Connection conn = JdbcUtils.getConnection(null, url, user, password);
-                       return new Db(conn);
+                       return new Db(conn, mode);
                } catch (SQLException e) {
                        throw new IciqlException(e);
                }
        }
 
        public static Db open(String url, String user, char[] password) {
+               return open(url, user, password, Mode.PROD);
+       }
+
+       public static Db open(String url, String user, char[] password, Mode mode) {
                try {
                        Connection conn = JdbcUtils.getConnection(null, url, user, password == null ? null : new String(password));
-                       return new Db(conn);
+                       return new Db(conn, mode);
                } catch (SQLException e) {
                        throw new IciqlException(e);
                }
        }
 
+       public static Db open(DataSource ds) {
+               return open(ds, Mode.PROD);
+       }
+
        /**
         * Create a new database instance using a data source. This method is fast,
         * so that you can always call open() / close() on usage.
         *
         * @param ds
         *            the data source
+        * @param mode
+        *            the runtime mode
         * @return the database instance.
         */
-       public static Db open(DataSource ds) {
+       public static Db open(DataSource ds, Mode mode) {
                try {
-                       return new Db(ds.getConnection());
+                       return new Db(ds.getConnection(), mode);
                } catch (SQLException e) {
                        throw new IciqlException(e);
                }
        }
 
        public static Db open(Connection conn) {
-               return new Db(conn);
+               return open(conn, Mode.PROD);
+       }
+
+       public static Db open(Connection conn, Mode mode) {
+               return new Db(conn, mode);
+       }
+
+       /**
+        * Returns the Iciql runtime mode.
+        *
+        * @return the runtime mode
+        */
+       public Mode getMode() {
+               return mode;
        }
 
        /**
@@ -806,4 +840,17 @@ public class Db implements AutoCloseable {
                return this.autoSavePoint;
        }
 
+       /**
+        *
+        * @author James Moger
+        *
+        */
+       class NoExternalDaoStatements implements DaoStatementProvider {
+
+               @Override
+               public String getStatement(String idOrStatement) {
+                       return idOrStatement;
+               }
+
+       }
 }
index 524faa8657c80cba93cb998663c3a61f183eadb4..b303372b32c4a74c71f0cfff9997e34c6d7772af 100644 (file)
@@ -726,6 +726,25 @@ public interface Iciql {
        public @interface IQIgnore{\r
        }\r
 \r
+       /**\r
+        * The runtime mode for Iciql.\r
+        */\r
+       public static enum Mode {\r
+\r
+               DEV, TEST, PROD;\r
+\r
+               public static Mode fromValue(String value) {\r
+\r
+                       for (Mode mode : values()) {\r
+                               if (mode.name().equalsIgnoreCase(value)) {\r
+                                       return mode;\r
+                               }\r
+                       }\r
+\r
+                       return PROD;\r
+               }\r
+       }\r
+\r
        /**\r
         * This method is called to let the table define the primary key, indexes,\r
         * and the table name.\r
@@ -767,6 +786,18 @@ public interface Iciql {
                 */\r
                Class<T> getJavaType();\r
 \r
+\r
+               /**\r
+                * Set the runtime mode.\r
+                * <p>\r
+                * Allows type adapters to adapt type mappings based on the runtime\r
+                * mode.\r
+                * </p>\r
+                *\r
+                * @param mode\r
+                */\r
+               void setMode(Mode mode);\r
+\r
                /**\r
                 * Serializes your Java object into a JDBC object.\r
                 *\r
index 17ee763f2aaa8fb1f1827e8f941f588133fb0145..d8a9ebdfd2a9513b51016974fc2765c6bd7b6769 100644 (file)
@@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import com.iciql.Iciql.ConstraintDeleteType;
 import com.iciql.Iciql.ConstraintUpdateType;
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 import com.iciql.TableDefinition.ConstraintForeignKeyDefinition;
 import com.iciql.TableDefinition.ConstraintUniqueDefinition;
 import com.iciql.TableDefinition.FieldDefinition;
@@ -50,6 +51,7 @@ public class SQLDialectDefault implements SQLDialect {
        int databaseMinorVersion;
        String databaseName;
        String productVersion;
+       Mode mode;
        Map<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>> typeAdapters;
 
        public SQLDialectDefault() {
@@ -76,6 +78,8 @@ public class SQLDialectDefault implements SQLDialect {
                } catch (SQLException e) {
                        throw new IciqlException(e, "failed to retrieve database metadata!");
                }
+
+               mode = db.getMode();
        }
 
        @Override
@@ -446,12 +450,13 @@ public class SQLDialectDefault implements SQLDialect {
 
        @Override
        public DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               DataTypeAdapter<?> dtt = typeAdapters.get(typeAdapter);
-               if (dtt == null) {
-                       dtt = Utils.newObject(typeAdapter);
-                       typeAdapters.put(typeAdapter, dtt);
+               DataTypeAdapter<?> dta = typeAdapters.get(typeAdapter);
+               if (dta == null) {
+                       dta = Utils.newObject(typeAdapter);
+                       typeAdapters.put(typeAdapter, dta);
                }
-               return dtt;
+               dta.setMode(mode);
+               return dta;
        }
 
        @SuppressWarnings("unchecked")
@@ -462,19 +467,19 @@ public class SQLDialectDefault implements SQLDialect {
                        return value;
                }
 
-               DataTypeAdapter<T> dtt = (DataTypeAdapter<T>) getAdapter(typeAdapter);
-               return dtt.serialize(value);
+               DataTypeAdapter<T> dta = (DataTypeAdapter<T>) getAdapter(typeAdapter);
+               return dta.serialize(value);
        }
 
        @Override
        public Object deserialize(Object value, Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               DataTypeAdapter<?> dtt = typeAdapters.get(typeAdapter);
-               if (dtt == null) {
-                       dtt = Utils.newObject(typeAdapter);
-                       typeAdapters.put(typeAdapter, dtt);
+               if (typeAdapter == null) {
+                       // pass-through
+                       return value;
                }
 
-               return dtt.deserialize(value);
+               DataTypeAdapter<?> dta = getAdapter(typeAdapter);
+               return dta.deserialize(value);
        }
 
        @Override
index b07b7b55a96ee6b2f1e8e7e7e66ab6277c2ca758..8d23cfdc79a9ec634262514c781cc5da5c6ee4d7 100644 (file)
@@ -18,6 +18,7 @@ package com.iciql.adapter;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 
 /**
  * Base class for inserting/retrieving a Java Object (de)serialized as JSON
@@ -39,10 +40,17 @@ import com.iciql.Iciql.DataTypeAdapter;
  */
 public abstract class GsonTypeAdapter<T> implements DataTypeAdapter<T> {
 
+       protected Mode mode;
+
        protected Gson gson() {
                return new GsonBuilder().create();
        }
 
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "TEXT";
index c475817383b86ead17e733fe4d54a1da2497a560..df2449501737c7637536ab69a07e4b4d491f3082 100644 (file)
@@ -25,9 +25,9 @@ import java.io.ObjectOutputStream;
 import java.sql.Blob;
 import java.sql.SQLException;
 
-import com.iciql.Iciql;
-import com.iciql.IciqlException;
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
+import com.iciql.IciqlException;
 
 /**
  * Base class for inserting/retrieving a Java Object as a BLOB field using Java Serialization.
@@ -44,6 +44,13 @@ import com.iciql.Iciql.DataTypeAdapter;
  */
 public abstract class JavaSerializationTypeAdapter<T> implements DataTypeAdapter<T> {
 
+       protected Mode mode;
+
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public final String getDataType() {
                return "BLOB";
index fe4541ca5804c89a7928a3b9c93b4bc7bac9bff4..da3b20b6546d96a8eac0e6eea8fd24c053c2b90e 100644 (file)
@@ -21,16 +21,24 @@ import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.nodes.Tag;
 
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 
 /**
  * Base class for inserting/retrieving a Java Object (de)serialized as YAML using SnakeYaml.
  */
 public abstract class SnakeYamlTypeAdapter<T> implements DataTypeAdapter<T> {
 
+       protected Mode mode;
+
        protected Yaml yaml() {
                return new Yaml();
        }
 
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "TEXT";
index 5e152df34244e15cef2445a8ee36ffab4ee1d7e3..a554724f87e5416dbca0309d8a85321895b8edf7 100644 (file)
@@ -17,6 +17,7 @@
 package com.iciql.adapter;
 
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 import com.thoughtworks.xstream.XStream;
 
 /**
@@ -24,10 +25,17 @@ import com.thoughtworks.xstream.XStream;
  */
 public class XStreamTypeAdapter implements DataTypeAdapter<Object> {
 
+       protected Mode mode;
+
        protected XStream xstream() {
                return new XStream();
        }
 
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "TEXT";
index c4fbd6af4e166ad8529c03a3e1803474bcf11752..01d2834e696256aa7fec2c075a24afdbea2f6f56 100644 (file)
@@ -20,12 +20,20 @@ import java.sql.SQLException;
 import org.postgresql.util.PGobject;
 
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 
 /**
  * Handles transforming raw strings to/from the Postgres JSON data type.
  */
 public class JsonStringAdapter implements DataTypeAdapter<String> {
 
+       protected Mode mode;
+
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "json";
index cc2d9c4a33a33cc0564c43099143533d3d76a69d..9d7388b8f97ee2fca21f7a33e5df2af0fa5d743f 100644 (file)
@@ -20,12 +20,20 @@ import java.sql.SQLException;
 import org.postgresql.util.PGobject;
 
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 
 /**
  * Handles transforming raw strings to/from the Postgres JSONB data type.
  */
 public class JsonbStringAdapter implements DataTypeAdapter<String> {
 
+       protected Mode mode;
+
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "jsonb";
index defe9f925e4fa95f254e3d09ecde1fbb7a52a3ae..0aea77e912018677e6ba5cf87715ffb1546b6e5b 100644 (file)
@@ -20,12 +20,20 @@ import java.sql.SQLException;
 import org.postgresql.util.PGobject;
 
 import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 
 /**
  * Handles transforming raw strings to/from the Postgres XML data type.
  */
 public class XmlStringAdapter implements DataTypeAdapter<String> {
 
+       protected Mode mode;
+
+       @Override
+       public void setMode(Mode mode) {
+               this.mode = mode;
+       }
+
        @Override
        public String getDataType() {
                return "xml";
index 70fc25e9e8efa394e0cb8dfe9b608df9a1b194c9..dc194855d4b044fd54505f40e217b70640d2f029 100644 (file)
@@ -35,6 +35,13 @@ Let's take a look at *InvoiceAdapterImpl*.
 ---JAVA---\r
 public class InvoiceAdapterImpl implements DataTypeAdapter<Invoice> {\r
 \r
+    Mode mode;\r
+    \r
+    @Override\r
+    public void setMode(Mode mode) {\r
+        this.mode = mode;\r
+    }\r
+\r
     @Override\r
     public String getDataType() {\r
         return "jsonb";\r
@@ -76,6 +83,10 @@ public class InvoiceAdapterImpl implements DataTypeAdapter<Invoice> {
 \r
 Here you can see how the *InvoiceTypeAdapter* defines a [Postgres JSONB data type](http://www.postgresql.org/docs/9.4/static/datatype-json.html) and automatically handles JSON (de)serialization with [Google Gson](https://code.google.com/p/google-gson) so that the database gets the content in a form that it requires but we can continue to work with objects in Java.\r
 \r
+### Runtime Mode\r
+\r
+Data type adapters can respond to the Iciql runtime mode (`DEV`, `TEST`, or `PROD`) allowing them to change their behavior. This is useful for targetting a data type that might be available in your production database but may not be available in your development or testing database.\r
+\r
 ### Custom annotations\r
 \r
 It is a little verbose to repeat `@TypeAdapter(InvoiceAdapterImpl.class)` everywhere you want to use your adapter.\r