Skip to content

Instantly share code, notes, and snippets.

@elucash
Created February 22, 2016 05:24
Show Gist options
  • Save elucash/955499dc6569669434df to your computer and use it in GitHub Desktop.
Save elucash/955499dc6569669434df to your computer and use it in GitHub Desktop.
Creating intercepting wrappers for type adapters
package abc;
import com.google.common.base.Function;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.Optional;
import java.util.ServiceLoader;
import javax.annotation.Nullable;
import org.immutables.mongo.Mongo;
import org.immutables.mongo.types.TimeInstant;
import org.immutables.value.Value;
interface WithModifiedOn {
WithModifiedOn withModifiedOn(TimeInstant timestamp);
Optional<TimeInstant> modifiedOn();
}
@Mongo.Repository
@Value.Immutable
@org.immutables.gson.Gson.TypeAdapters
interface SampleDocument extends WithModifiedOn {
String field1();
String field2();
}
class SerializeInterceptor<T> {
private final Class<T> interceptedRawType;
private final Function<T, T> transformation;
SerializeInterceptor(Class<T> interceptedRawType, Function<T, T> transformation) {
this.interceptedRawType = interceptedRawType;
this.transformation = transformation;
}
TypeAdapterFactory wrap(TypeAdapterFactory factory) {
return new TypeAdapterFactory() {
@Override
public <X> TypeAdapter<X> create(Gson gson, TypeToken<X> type) {
@Nullable TypeAdapter<X> delegateAdapter = factory.create(gson, type);
if (delegateAdapter != null) {
if (interceptedRawType.isAssignableFrom(type.getRawType())) {
return wrapAdapter(delegateAdapter);
}
return delegateAdapter;
}
return null;
}
};
}
<X> TypeAdapter<X> wrapAdapter(TypeAdapter<X> adapter) {
return new TypeAdapter<X>() {
// safe unchecked: checked in runtime using Class.isAssignableFrom
@SuppressWarnings("unchecked")
@Override
public void write(JsonWriter out, X value) throws IOException {
X transformedValue = (X) transformation.apply((T) value);
adapter.write(out, transformedValue);
}
@Override
public X read(JsonReader in) throws IOException {
return adapter.read(in);
}
};
}
public static void main(String... args) {
GsonBuilder gsonBuilder = new GsonBuilder();
SerializeInterceptor<WithModifiedOn> interceptor =
new SerializeInterceptor<>(WithModifiedOn.class, new Function<WithModifiedOn, WithModifiedOn>() {
@Override
public WithModifiedOn apply(WithModifiedOn input) {
return input.withModifiedOn(TimeInstant.of(System.currentTimeMillis()));
}
});
for (TypeAdapterFactory factory : ServiceLoader.load(TypeAdapterFactory.class)) {
gsonBuilder.registerTypeAdapterFactory(interceptor.wrap(factory));
}
Gson gson = gsonBuilder.create();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment