Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions RosettaCore/src/main/java/com/hubspot/rosetta/Rosetta.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -19,6 +22,7 @@ public enum Rosetta {

private static final List<Module> MODULES = new CopyOnWriteArrayList<Module>(defaultModules());
private static final AtomicReference<ObjectMapper> MAPPER = new AtomicReference<ObjectMapper>(cloneAndCustomize(new ObjectMapper()));
private static final Map<String, ObjectMapper> NAMED_MAPPERS = new ConcurrentHashMap<String, ObjectMapper>();

public static ObjectMapper getMapper() {
return INSTANCE.get();
Expand Down Expand Up @@ -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<Module> defaultModules() {
Expand All @@ -70,4 +78,57 @@ private static List<Module> defaultModules() {

return defaultModules;
}

public static void registerNamedMapper(String name, ObjectMapper objectMapper) {

NAMED_MAPPERS.put(name, cloneAndCustomize(objectMapper));
}

public static void registerNamedMappers(Map<String, ObjectMapper> objectMappers) {

for (Map.Entry<String, ObjectMapper> 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<String, ObjectMapper> removeNamedMappers(Collection<String> names) {

Map<String, ObjectMapper> removedMappers = new ConcurrentHashMap<>();

for (String name : names) {

ObjectMapper objectMapper = removeNamedMapper(name);

if (objectMapper != null) {

removedMappers.put(name, removeNamedMapper(name));

}

}

return removedMappers;
}

public static Map<String, ObjectMapper> getNamedMappers() {

return new ConcurrentHashMap<>(NAMED_MAPPERS);
}

public static ObjectMapper getNamedMapper(String mapperName) {

return NAMED_MAPPERS.get(mapperName);
}

public static void clearNamedMappers() {

NAMED_MAPPERS.clear();
}

}
9 changes: 9 additions & 0 deletions RosettaJdbi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -39,5 +43,10 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -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<BindWithRosetta, Object> {
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();
Expand All @@ -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<? extends Annotation> 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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
);
}

}
};
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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)
);
}

}
};
}
}


}
Loading