diff --git a/RosettaCore/src/main/java/com/hubspot/rosetta/Rosetta.java b/RosettaCore/src/main/java/com/hubspot/rosetta/Rosetta.java index 2cda342d..5859a011 100644 --- a/RosettaCore/src/main/java/com/hubspot/rosetta/Rosetta.java +++ b/RosettaCore/src/main/java/com/hubspot/rosetta/Rosetta.java @@ -7,9 +7,12 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; +import java.util.Collection; /** * Static public APIs to get/set some Rosetta globals. @@ -19,6 +22,7 @@ public enum Rosetta { private static final List MODULES = new CopyOnWriteArrayList(defaultModules()); private static final AtomicReference MAPPER = new AtomicReference(cloneAndCustomize(new ObjectMapper())); + private static final Map NAMED_MAPPERS = new ConcurrentHashMap(); public static ObjectMapper getMapper() { return INSTANCE.get(); @@ -54,6 +58,10 @@ private void set(ObjectMapper mapper) { private void add(Module module) { MODULES.add(module); MAPPER.get().registerModule(module); + + for (ObjectMapper objectMapper : NAMED_MAPPERS.values()) { + objectMapper.registerModule(module); + } } private static List defaultModules() { @@ -70,4 +78,57 @@ private static List defaultModules() { return defaultModules; } + + public static void registerNamedMapper(String name, ObjectMapper objectMapper) { + + NAMED_MAPPERS.put(name, cloneAndCustomize(objectMapper)); + } + + public static void registerNamedMappers(Map objectMappers) { + + for (Map.Entry entry : objectMappers.entrySet()) { + + NAMED_MAPPERS.put(entry.getKey(), cloneAndCustomize(entry.getValue())); + } + } + + public static ObjectMapper removeNamedMapper(String name) { + + return NAMED_MAPPERS.remove(name); + } + + public static Map removeNamedMappers(Collection names) { + + Map removedMappers = new ConcurrentHashMap<>(); + + for (String name : names) { + + ObjectMapper objectMapper = removeNamedMapper(name); + + if (objectMapper != null) { + + removedMappers.put(name, removeNamedMapper(name)); + + } + + } + + return removedMappers; + } + + public static Map getNamedMappers() { + + return new ConcurrentHashMap<>(NAMED_MAPPERS); + } + + public static ObjectMapper getNamedMapper(String mapperName) { + + return NAMED_MAPPERS.get(mapperName); + } + + public static void clearNamedMappers() { + + NAMED_MAPPERS.clear(); + } + } diff --git a/RosettaJdbi/pom.xml b/RosettaJdbi/pom.xml index 8ddb77df..60176278 100644 --- a/RosettaJdbi/pom.xml +++ b/RosettaJdbi/pom.xml @@ -23,6 +23,10 @@ com.fasterxml.jackson.core jackson-databind + + com.fasterxml.jackson.core + jackson-core + junit junit @@ -39,5 +43,10 @@ test-jar test + + com.h2database + h2 + test + diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaJdbiBinder.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaJdbiBinder.java index adb7a4dd..d94adbc9 100644 --- a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaJdbiBinder.java +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaJdbiBinder.java @@ -8,12 +8,14 @@ import com.fasterxml.jackson.databind.JsonNode; import org.skife.jdbi.v2.sqlobject.Binder; +import java.lang.annotation.Annotation; + public enum RosettaJdbiBinder implements Binder { INSTANCE; @Override public void bind(final SQLStatement q, BindWithRosetta bind, Object arg) { - ObjectMapper objectMapper = RosettaObjectMapperOverride.resolve(q.getContext()); + ObjectMapper objectMapper = RosettaObjectMapperOverride.resolveStatementBinder(q.getContext()); JsonNode node = objectMapper.valueToTree(arg); String prefix = bind.value(); @@ -31,4 +33,32 @@ public void bind(String key, Object value) { } }); } + + public void bind(final SQLStatement q, final String prefix, Object arg) { + + RosettaJdbiBinder.INSTANCE.bind(q, new BindWithRosetta() { + + @Override + public Class annotationType() { + return BindWithRosetta.class; + } + + @Override + public String value() { + if (prefix != null) { + return prefix; + } + + return ""; + } + + }, arg); + + + } + + public void bind(final SQLStatement q,Object arg) { + bind(q,"",arg); + } + } diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaMapperFactory.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaMapperFactory.java index 6fc1b44c..a7f8f671 100644 --- a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaMapperFactory.java +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaMapperFactory.java @@ -3,6 +3,7 @@ import java.sql.ResultSet; import java.sql.SQLException; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.skife.jdbi.v2.BuiltInArgumentFactory; import org.skife.jdbi.v2.ResultSetMapperFactory; @@ -21,7 +22,7 @@ public boolean accepts(@SuppressWarnings("rawtypes") Class type, StatementContex @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public ResultSetMapper mapperFor(Class type, StatementContext ctx) { - ObjectMapper objectMapper = RosettaObjectMapperOverride.resolve(ctx); + ObjectMapper objectMapper = RosettaObjectMapperOverride.resolveResultSetMapper(ctx); final RosettaMapper mapper = new RosettaMapper(type, objectMapper, extractTableName(ctx.getRewrittenSql())); return new ResultSetMapper() { diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapper.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapper.java new file mode 100644 index 00000000..200c9f1f --- /dev/null +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapper.java @@ -0,0 +1,62 @@ +package com.hubspot.rosetta.jdbi; + +import com.hubspot.rosetta.Rosetta; +import org.skife.jdbi.v2.SQLStatement; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizer; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizerFactory; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizingAnnotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.sql.SQLException; + +@Retention(RetentionPolicy.RUNTIME) +@SqlStatementCustomizingAnnotation(RosettaObjectMapper.CustomizerFactory.class) +public @interface RosettaObjectMapper { + + String value() default ""; + + final class CustomizerFactory implements SqlStatementCustomizerFactory { + + @Override + public SqlStatementCustomizer createForMethod(Annotation annotation, Class sqlObjectType, Method method) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForType(Annotation annotation, Class sqlObjectType) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForParameter( + Annotation annotation, Class sqlObjectType, Method method, Object arg) { + return getCustomizer(annotation); + } + + private SqlStatementCustomizer getCustomizer(Annotation annotation) { + + RosettaObjectMapper rosettaResultSetObjectMapper = (RosettaObjectMapper) annotation; + final String mapperName = rosettaResultSetObjectMapper.value(); + + return new SqlStatementCustomizer() { + + @Override + public void apply(SQLStatement q) throws SQLException { + + if (mapperName != null && !mapperName.isEmpty()) { + q.define(RosettaObjectMapperOverride.RESULTSET_MAPPER_ATTRIBUTE_NAME, + Rosetta.getNamedMapper(mapperName) + ); + q.define(RosettaObjectMapperOverride.STATEMENT_BINDER_ATTRIBUTE_NAME, + Rosetta.getNamedMapper(mapperName) + ); + } + + } + }; + } + } +} diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapperOverride.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapperOverride.java index 143c3f19..d04adf4f 100644 --- a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapperOverride.java +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaObjectMapperOverride.java @@ -1,5 +1,6 @@ package com.hubspot.rosetta.jdbi; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.hubspot.rosetta.Rosetta; import com.hubspot.rosetta.internal.RosettaModule; @@ -9,7 +10,8 @@ import org.skife.jdbi.v2.StatementContext; public class RosettaObjectMapperOverride { - public static final String ATTRIBUTE_NAME = "_rosetta_object_mapper"; + public static final String RESULTSET_MAPPER_ATTRIBUTE_NAME = "_rosetta_object_mapper_resultset_mapper"; + public static final String STATEMENT_BINDER_ATTRIBUTE_NAME = "_rosetta_object_mapper_statement_binder"; private final ObjectMapper objectMapper; @@ -18,19 +20,44 @@ public RosettaObjectMapperOverride(ObjectMapper objectMapper) { } public void override(DBI dbi) { - dbi.define(ATTRIBUTE_NAME, objectMapper); + dbi.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); + dbi.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); + + } + public void overrideResultSetMapper(DBI dbi) { + dbi.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); + } + public void overrideStatementBinder(DBI dbi) { + dbi.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); } public void override(Handle handle) { - handle.define(ATTRIBUTE_NAME, objectMapper); + handle.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); + handle.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); } + public void overrideResultSetMapper(Handle handle) { + handle.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); + } + public void overrideStatementBinder(Handle handle) { + handle.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); } public void override(SQLStatement statement) { - statement.define(ATTRIBUTE_NAME, objectMapper); + statement.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); + statement.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); } + public void overrideResultSetMapper(SQLStatement statement) { + statement.define(RESULTSET_MAPPER_ATTRIBUTE_NAME, objectMapper); + } + public void overrideStatementBinder(SQLStatement statement) { + statement.define(STATEMENT_BINDER_ATTRIBUTE_NAME, objectMapper); + } + + public static ObjectMapper resolveResultSetMapper(StatementContext context) { + Object override = context.getAttribute(RESULTSET_MAPPER_ATTRIBUTE_NAME); + return override == null ? Rosetta.getMapper() : (ObjectMapper) override; } - public static ObjectMapper resolve(StatementContext context) { - Object override = context.getAttribute(ATTRIBUTE_NAME); + public static ObjectMapper resolveStatementBinder(StatementContext context) { + Object override = context.getAttribute(STATEMENT_BINDER_ATTRIBUTE_NAME); return override == null ? Rosetta.getMapper() : (ObjectMapper) override; } } diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaResultSetObjectMapper.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaResultSetObjectMapper.java new file mode 100644 index 00000000..42e82213 --- /dev/null +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaResultSetObjectMapper.java @@ -0,0 +1,61 @@ +package com.hubspot.rosetta.jdbi; + +import com.hubspot.rosetta.Rosetta; +import org.skife.jdbi.v2.SQLStatement; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizer; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizerFactory; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizingAnnotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.sql.SQLException; + +@Retention(RetentionPolicy.RUNTIME) +@SqlStatementCustomizingAnnotation(RosettaResultSetObjectMapper.CustomizerFactory.class) +public @interface RosettaResultSetObjectMapper { + + String value() default ""; + + final class CustomizerFactory implements SqlStatementCustomizerFactory { + + @Override + public SqlStatementCustomizer createForMethod(Annotation annotation, Class sqlObjectType, Method method) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForType(Annotation annotation, Class sqlObjectType) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForParameter( + Annotation annotation, Class sqlObjectType, Method method, Object arg) { + return getCustomizer(annotation); + } + + private SqlStatementCustomizer getCustomizer(Annotation annotation) { + + RosettaResultSetObjectMapper rosettaResultSetObjectMapper = (RosettaResultSetObjectMapper) annotation; + final String mapperName = rosettaResultSetObjectMapper.value(); + + return new SqlStatementCustomizer() { + + @Override + public void apply(SQLStatement q) throws SQLException { + + if (mapperName != null && !mapperName.isEmpty()) { + q.define(RosettaObjectMapperOverride.RESULTSET_MAPPER_ATTRIBUTE_NAME, + Rosetta.getNamedMapper(mapperName) + ); + } + + } + }; + } + } + + +} diff --git a/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaStatementBinderObjectMapper.java b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaStatementBinderObjectMapper.java new file mode 100644 index 00000000..ad8d007a --- /dev/null +++ b/RosettaJdbi/src/main/java/com/hubspot/rosetta/jdbi/RosettaStatementBinderObjectMapper.java @@ -0,0 +1,59 @@ +package com.hubspot.rosetta.jdbi; + +import com.hubspot.rosetta.Rosetta; +import org.skife.jdbi.v2.SQLStatement; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizer; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizerFactory; +import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizingAnnotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.sql.SQLException; + +@Retention(RetentionPolicy.RUNTIME) +@SqlStatementCustomizingAnnotation(RosettaStatementBinderObjectMapper.CustomizerFactory.class) +public @interface RosettaStatementBinderObjectMapper { + + String value() default ""; + + final class CustomizerFactory implements SqlStatementCustomizerFactory { + + @Override + public SqlStatementCustomizer createForMethod(Annotation annotation, Class sqlObjectType, Method method) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForType(Annotation annotation, Class sqlObjectType) { + return getCustomizer(annotation); + } + + @Override + public SqlStatementCustomizer createForParameter( + Annotation annotation, Class sqlObjectType, Method method, Object arg) { + return getCustomizer(annotation); + } + + private SqlStatementCustomizer getCustomizer(Annotation annotation) { + + RosettaStatementBinderObjectMapper rosettaResultSetObjectMapper = (RosettaStatementBinderObjectMapper) annotation; + final String mapperName = rosettaResultSetObjectMapper.value(); + + return new SqlStatementCustomizer() { + + @Override + public void apply(SQLStatement q) throws SQLException { + + if (mapperName != null && !mapperName.isEmpty()) { + q.define(RosettaObjectMapperOverride.STATEMENT_BINDER_ATTRIBUTE_NAME, + Rosetta.getNamedMapper(mapperName) + ); + } + + } + }; + } + } +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/ObjectMapperResolutionTest.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/ObjectMapperResolutionTest.java new file mode 100644 index 00000000..70631991 --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/ObjectMapperResolutionTest.java @@ -0,0 +1,118 @@ +package com.hubspot.rosetta.jdbi; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hubspot.rosetta.Rosetta; +import com.hubspot.rosetta.jdbi.beans.MapperNameBean; +import com.hubspot.rosetta.jdbi.jackson.ObjectMapperResolutionTestModule; +import com.hubspot.rosetta.jdbi.sqlobjects.ObjectMapperResolverDao; +import org.junit.*; +import org.skife.jdbi.v2.DBI; +import org.skife.jdbi.v2.Handle; +import org.skife.jdbi.v2.Query; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class ObjectMapperResolutionTest { + + private DBI dbi; + private ObjectMapper dbiDefaultMapper; + private ObjectMapper dbiResultSetMapper; + private ObjectMapper dbiBinderMapper; + private ObjectMapper rosettaConfigurationDefaultMapper; + private ObjectMapper rosettaConfigurationResultSetMapper; + private ObjectMapper rosettaConfigurationBinderMapper; + private ObjectMapper bindWithRosettaConfigurationBinderMapper; + private ObjectMapper sqlObjectResultSetMapper; + private ObjectMapper sqlObjectBinderMapper; + + + @Before + public void setUp() { + + dbi = new DBI("jdbc:h2:~/test;MODE=PostgreSQL"); + + Rosetta.setMapper(getTaggedObjectMapper("globalMapper")); + + dbiDefaultMapper = getTaggedObjectMapper("dbiDefaultMapper"); + dbiResultSetMapper = getTaggedObjectMapper("dbiResultSetMapper"); + dbiBinderMapper = getTaggedObjectMapper("dbiBinderMapper"); + + rosettaConfigurationDefaultMapper = getTaggedObjectMapper("configDefaultMapper"); + rosettaConfigurationResultSetMapper = getTaggedObjectMapper("configResultSetMapper"); + rosettaConfigurationBinderMapper = getTaggedObjectMapper("configBinderMapper"); + sqlObjectResultSetMapper = getTaggedObjectMapper("configSqlObjectResultSetMapper"); + sqlObjectBinderMapper = getTaggedObjectMapper("configSqlObjectBinderMapper"); + + + Rosetta.registerNamedMapper("configDefaultMapper",rosettaConfigurationDefaultMapper); + Rosetta.registerNamedMapper("configResultSetMapper",rosettaConfigurationResultSetMapper); + Rosetta.registerNamedMapper("configBinderMapper",rosettaConfigurationBinderMapper); + Rosetta.registerNamedMapper("configSqlObjectResultSetMapper",sqlObjectResultSetMapper); + Rosetta.registerNamedMapper("configSqlObjectBinderMapper",sqlObjectBinderMapper); + + + bindWithRosettaConfigurationBinderMapper = getTaggedObjectMapper("bwrConfigBinderMapper"); + Rosetta.registerNamedMapper("bwrConfigBinderMapper", bindWithRosettaConfigurationBinderMapper); + + } + + @Test + public void itResolvesObjectMappersAcrossDBIHierarchyCorrectly() { + + new RosettaObjectMapperOverride(dbiResultSetMapper).overrideResultSetMapper(dbi); + new RosettaObjectMapperOverride(dbiBinderMapper).overrideStatementBinder(dbi); + + MapperNameBean mnb; + + try (Handle h = dbi.open()) { + + ObjectMapperResolverDao dao = h.attach(ObjectMapperResolverDao.class); + + mnb = dao.configMapperAndBinderWithArgBinder(new MapperNameBean()); + + assertThat(mnb.getBinderName().getName()).isEqualTo("bwrConfigBinderMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("configResultSetMapper"); + + mnb = dao.configMapperAndBinder(new MapperNameBean()); + + assertThat(mnb.getBinderName().getName()).isEqualTo("configBinderMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("configResultSetMapper"); + + mnb = dao.configDefaultMapper(new MapperNameBean()); + + assertThat(mnb.getBinderName().getName()).isEqualTo("configDefaultMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("configDefaultMapper"); + + mnb = dao.sqlObjectMappers(new MapperNameBean()); + + assertThat(mnb.getBinderName().getName()).isEqualTo("configSqlObjectBinderMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("configSqlObjectResultSetMapper"); + + mnb = dao.configResultSetMapperAndSqlObjectBinder(new MapperNameBean()); + + assertThat(mnb.getBinderName().getName()).isEqualTo("configSqlObjectBinderMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("configResultSetMapper"); + + Query q = h.createQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\""); + q.registerMapper(new RosettaMapperFactory()); + RosettaJdbiBinder.INSTANCE.bind(q, new MapperNameBean()); + mnb = q.mapTo(MapperNameBean.class).first(); + + assertThat(mnb.getBinderName().getName()).isEqualTo("dbiBinderMapper"); + assertThat(mnb.getMapperName().getName()).isEqualTo("dbiResultSetMapper"); + + } + } + + @After + public void tearDown() { + + Rosetta.clearNamedMappers(); + Rosetta.setMapper(new ObjectMapper()); + } + + private ObjectMapper getTaggedObjectMapper(final String name) { + return new ObjectMapper().registerModule(new ObjectMapperResolutionTestModule(name)); + } +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/RosettaMapperFactoryTest.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/RosettaMapperFactoryTest.java index 3f88c66c..4b45e5ac 100644 --- a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/RosettaMapperFactoryTest.java +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/RosettaMapperFactoryTest.java @@ -6,6 +6,7 @@ import com.hubspot.rosetta.beans.RosettaNamingBean; import com.hubspot.rosetta.beans.RosettaValueBean; import com.hubspot.rosetta.beans.StoredAsJsonBean; +import com.hubspot.rosetta.jdbi.beans.CircularBean; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/CircularBean.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/CircularBean.java similarity index 87% rename from RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/CircularBean.java rename to RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/CircularBean.java index 70d99e3e..c7bceb01 100644 --- a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/CircularBean.java +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/CircularBean.java @@ -1,4 +1,4 @@ -package com.hubspot.rosetta.jdbi; +package com.hubspot.rosetta.jdbi.beans; import java.util.List; diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/MapperNameBean.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/MapperNameBean.java new file mode 100644 index 00000000..e34f66a8 --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/MapperNameBean.java @@ -0,0 +1,23 @@ +package com.hubspot.rosetta.jdbi.beans; + +public class MapperNameBean { + + private NameBean binderName = new NameBean("value"); + private NameBean mapperName = new NameBean("value"); + + public NameBean getBinderName() { + return binderName; + } + + public void setBinderName(NameBean binderName) { + this.binderName = binderName; + } + + public NameBean getMapperName() { + return mapperName; + } + + public void setMapperName(NameBean mapperName) { + this.mapperName = mapperName; + } +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/NameBean.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/NameBean.java new file mode 100644 index 00000000..c45edb5f --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/beans/NameBean.java @@ -0,0 +1,19 @@ +package com.hubspot.rosetta.jdbi.beans; + +public class NameBean { + + public NameBean(String name) { + + this.name = name; + } + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameDeserializer.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameDeserializer.java new file mode 100644 index 00000000..44a643fa --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameDeserializer.java @@ -0,0 +1,34 @@ +package com.hubspot.rosetta.jdbi.jackson; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.hubspot.rosetta.jdbi.beans.NameBean; + +import java.io.IOException; + +public class ObjectMapperNameDeserializer extends JsonDeserializer { + + private final String mapperName; + + public ObjectMapperNameDeserializer(String mapperName) { + + this.mapperName = mapperName; + + } + + @Override + public NameBean deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + + String s = jsonParser.getValueAsString(); + + if (s.equals("value")) { + + return new NameBean(mapperName); + } + + return new NameBean(s); + } + +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameSerializer.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameSerializer.java new file mode 100644 index 00000000..d867b456 --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperNameSerializer.java @@ -0,0 +1,35 @@ +package com.hubspot.rosetta.jdbi.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.hubspot.rosetta.jdbi.beans.NameBean; + +import java.io.IOException; + +public class ObjectMapperNameSerializer extends JsonSerializer { + + private final String mapperName; + + public ObjectMapperNameSerializer(String mapperName) { + + this.mapperName = mapperName; + } + + @Override + public void serialize(NameBean nameBean, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { + + String s = nameBean.getName(); + + if (s.equals("value")) { + + jsonGenerator.writeString(mapperName); + } + + else { + + jsonGenerator.writeString(s); + } + } +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperResolutionTestModule.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperResolutionTestModule.java new file mode 100644 index 00000000..dc64777d --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/jackson/ObjectMapperResolutionTestModule.java @@ -0,0 +1,17 @@ +package com.hubspot.rosetta.jdbi.jackson; + +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.hubspot.rosetta.jdbi.beans.NameBean; + +public class ObjectMapperResolutionTestModule extends SimpleModule { + + public ObjectMapperResolutionTestModule(final String name) { + + addDeserializer(NameBean.class, new ObjectMapperNameDeserializer(name)); + addSerializer(NameBean.class, new ObjectMapperNameSerializer(name)); + setNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()); + } + + +} diff --git a/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/sqlobjects/ObjectMapperResolverDao.java b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/sqlobjects/ObjectMapperResolverDao.java new file mode 100644 index 00000000..652dcbc0 --- /dev/null +++ b/RosettaJdbi/src/test/java/com/hubspot/rosetta/jdbi/sqlobjects/ObjectMapperResolverDao.java @@ -0,0 +1,36 @@ +package com.hubspot.rosetta.jdbi.sqlobjects; + +import com.hubspot.rosetta.jdbi.*; +import com.hubspot.rosetta.jdbi.beans.MapperNameBean; +import org.skife.jdbi.v2.sqlobject.SqlQuery; +import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapperFactory; + +@RosettaResultSetObjectMapper("configSqlObjectResultSetMapper") +@RosettaStatementBinderObjectMapper("configSqlObjectBinderMapper") +@RegisterMapperFactory(RosettaMapperFactory.class) +public interface ObjectMapperResolverDao { + + @RosettaResultSetObjectMapper("configResultSetMapper") + @RosettaStatementBinderObjectMapper("configBinderMapper") + @SqlQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\"") + MapperNameBean configMapperAndBinderWithArgBinder( + @RosettaStatementBinderObjectMapper("bwrConfigBinderMapper") @BindWithRosetta MapperNameBean mnb); + + @RosettaResultSetObjectMapper("configResultSetMapper") + @RosettaStatementBinderObjectMapper("configBinderMapper") + @SqlQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\"") + MapperNameBean configMapperAndBinder(@BindWithRosetta MapperNameBean mnb); + + @RosettaObjectMapper("configDefaultMapper") + @SqlQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\"") + MapperNameBean configDefaultMapper(@BindWithRosetta MapperNameBean mnb); + + + @SqlQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\"") + MapperNameBean sqlObjectMappers(@BindWithRosetta MapperNameBean mnb); + + @RosettaResultSetObjectMapper("configResultSetMapper") + @SqlQuery("SELECT 'value' \"mapper_name\", :binder_name \"binder_name\"") + MapperNameBean configResultSetMapperAndSqlObjectBinder(@BindWithRosetta MapperNameBean mnb); + +} diff --git a/pom.xml b/pom.xml index 02ffb25b..f4b3749a 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,12 @@ mysql-connector-java 5.1.38 + + com.h2database + h2 + 1.4.190 + test +