## Data Type Adapters

Data type adapters allow you to extend Iciql's support for field data types.

For example, you might want to take advantage of the [Postgres JSON/JSONB support](http://www.postgresql.org/docs/9.4/static/datatype-json.html) in 9.3/9.4 but instead of directly handling JSON text documents you might want to represent that JSON as a domain object and serialize/deserialize to JSON only when executing an SQL operation.

Data type adapters give you this flexibility.

**NOTE:** Data type adapters are reused within a Db instance and are not inherently thread-safe. You must handle thread-safety on your own, if it is an issue.

### An example

Consider the following model class.

---JAVA---
@IQTable
public class Invoices {
    
    @IQColumn(primaryKey = true, autoIncrement = true)
    public long _id;
    
    @IQColumn
    Date received;
    
    @IQColumn
    @TypeAdapter(InvoiceAdapterImpl.class)
    Invoice invoice;
}
---JAVA---

This is a really simple table with three columns, but the third column uses a type adapter to map our *invoice* object field to an SQL type.  You can use the `@TypeAdapter` annotation either on the field definition or on the class definition of your domain model.

Let's take a look at *InvoiceAdapterImpl*.

---JAVA---
public class InvoiceAdapterImpl implements DataTypeAdapter<Invoice> {

    Mode mode;
    
    @Override
    public void setMode(Mode mode) {
        this.mode = mode;
    }

    @Override
    public String getDataType() {
        return "jsonb";
    }

    @Override
    public Class<Invoice> getJavaType() {
        return Invoice.class;
    }

    Gson gson() {
        return new GsonBuilder().create();
    }

    @Override
    public Object serialize(Invoice value) {
        String json = gson().toJson(value);
        PGobject pg = new PGobject();
        pg.setType(getDataType());
        try {
            pg.setValue(json);
        } catch (SQLException e) {
            // ignore, never thrown
        }
        return pg;
    }

    @Override
    public Invoice deserialize(Object value) {

        // the incoming object is always represented as a string
        final String json = value.toString();
        final Invoice invoice = gson().fromJson(json, getJavaType());

        return invoice;
    }
}
---JAVA---

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.

### Runtime Mode

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.

### Custom annotations

It is a little verbose to repeat `@TypeAdapter(InvoiceAdapterImpl.class)` everywhere you want to use your adapter.

To simplify this, you can implement your own annotation which specifies your type adapter.

---JAVA---
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@TypeAdapter(InvoiceAdapterImpl.class)
public @interface InvoiceAdapter { }
---JAVA---

### Included Data Type Adapters

The following adapters are included in Iciql.  They may require an optional dependency such as Gson, XStream, or SnakeYaml.

<table class="table">
<tr><td colspan="4"><b>Common Type Adapters</b></tr>
<tr><td><i>Adapter</i></td><td><i>Java</i></td><td><i>SQL</i></td><td><i>Description</i></td></tr>

<tr><td>com.iciql.adapter.JavaSerializationTypeAdapter</td><td>Object</td><td>BLOB</td><td>Uses Java serialization to (de)serialize your object</td></tr>

<tr><td>com.iciql.adapter.GsonTypeAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>TEXT</td><td>
Uses Google Gson to (de)serialize your object as JSON</td></tr>

<tr><td>com.iciql.adapter.XStreamTypeAdapter</td><td>Object</td><td>TEXT</td><td>
Uses XStream to (de)serialize your object as XML</td></tr>

<tr><td>com.iciql.adapter.SnakeYamlTypeAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>TEXT</td><td>
Uses SnakeYaml to (de)serialize your object as YAML</td></tr>

<tr><td colspan="4"><b>PostgreSQL Type Adapters</b></tr>
<tr><td><i>Object Adapters</i></td><td><i>Java</i></td><td><i>SQL</i></td><td><i>Description</i></td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonObjectAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>JSON</td><td>
Uses Google Gson to (de)serialize your object as JSON</td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonbObjectAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>JSONB</td><td>
Uses Google Gson to (de)serialize your object as JSONB</td></tr>

<tr><td>com.iciql.adapter.postgresql.XmlObjectAdapter</td><td>Object</td><td>XML</td><td>
Uses XStream to (de)serialize your object as XML</td></tr>

<tr><td colspan="4"><i>String Adapters</i></td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonStringAdapter</td><td>String</td><td>JSON</td><td>
Maps the JSON data type to a java.lang.String</td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonbStringAdapter</td><td>String</td><td>JSONB</td><td>
Maps the JSONB data type to a java.lang.String</td></tr>

<tr><td>com.iciql.adapter.postgresql.XmlStringAdapter</td><td>String</td><td>XML</td><td>
Maps the XML data type to a java.lang.String</td></tr>

</table>