mirror of https://github.com/apache/jclouds.git
make it possible to deserialize into ctors that have immutable collection parameters
This commit is contained in:
parent
7596205774
commit
ef2718629f
|
@ -26,6 +26,7 @@ import javax.inject.Inject;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapter;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
@ -84,10 +85,10 @@ public class CloudStackParserModule extends AbstractModule {
|
||||||
|
|
||||||
public static final class Adapter<E> extends TypeAdapter<Iterable<E>> {
|
public static final class Adapter<E> extends TypeAdapter<Iterable<E>> {
|
||||||
|
|
||||||
private final IterableTypeAdapterFactory.IterableTypeAdapter<E> delegate;
|
private final IterableTypeAdapter<E> delegate;
|
||||||
|
|
||||||
public Adapter(TypeAdapter<E> elementAdapter) {
|
public Adapter(TypeAdapter<E> elementAdapter) {
|
||||||
this.delegate = new IterableTypeAdapterFactory.IterableTypeAdapter<E>(elementAdapter);
|
this.delegate = new IterableTypeAdapter<E>(elementAdapter);
|
||||||
nullSafe();
|
nullSafe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapter;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
@ -63,10 +64,10 @@ public class KeystoneParserModule extends AbstractModule {
|
||||||
|
|
||||||
public static final class Adapter<E> extends TypeAdapter<Set<E>> {
|
public static final class Adapter<E> extends TypeAdapter<Set<E>> {
|
||||||
|
|
||||||
private final SetTypeAdapterFactory.SetTypeAdapter<E> delegate;
|
private final SetTypeAdapter<E> delegate;
|
||||||
|
|
||||||
public Adapter(TypeAdapter<E> elementAdapter) {
|
public Adapter(TypeAdapter<E> elementAdapter) {
|
||||||
this.delegate = new SetTypeAdapterFactory.SetTypeAdapter<E>(elementAdapter);
|
this.delegate = new SetTypeAdapter<E>(elementAdapter);
|
||||||
nullSafe();
|
nullSafe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,10 @@ import org.jclouds.json.internal.NamingStrategies.ExtractNamed;
|
||||||
import org.jclouds.json.internal.NamingStrategies.ExtractSerializedName;
|
import org.jclouds.json.internal.NamingStrategies.ExtractSerializedName;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.CollectionTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.CollectionTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.FluentIterableTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.FluentIterableTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ImmutableListTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ImmutableSetTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ListTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MultimapTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MultimapTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
||||||
|
@ -88,9 +91,10 @@ public class GsonModule extends AbstractModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
Gson provideGson(TypeAdapter<JsonBall> jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
|
Gson provideGson(TypeAdapter<JsonBall> jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
|
||||||
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings,
|
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings,
|
||||||
OptionalTypeAdapterFactory optional, SetTypeAdapterFactory set, MapTypeAdapterFactory map,
|
OptionalTypeAdapterFactory optional, SetTypeAdapterFactory set, ImmutableSetTypeAdapterFactory immutableSet,
|
||||||
MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
|
MapTypeAdapterFactory map, MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
|
||||||
CollectionTypeAdapterFactory collection, FluentIterableTypeAdapterFactory fluentIterable,
|
CollectionTypeAdapterFactory collection, ListTypeAdapterFactory list,
|
||||||
|
ImmutableListTypeAdapterFactory immutableList, FluentIterableTypeAdapterFactory fluentIterable,
|
||||||
DefaultExclusionStrategy exclusionStrategy) {
|
DefaultExclusionStrategy exclusionStrategy) {
|
||||||
|
|
||||||
FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(
|
FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(
|
||||||
|
@ -109,7 +113,10 @@ public class GsonModule extends AbstractModule {
|
||||||
builder.registerTypeAdapterFactory(optional);
|
builder.registerTypeAdapterFactory(optional);
|
||||||
builder.registerTypeAdapterFactory(iterable);
|
builder.registerTypeAdapterFactory(iterable);
|
||||||
builder.registerTypeAdapterFactory(collection);
|
builder.registerTypeAdapterFactory(collection);
|
||||||
|
builder.registerTypeAdapterFactory(list);
|
||||||
|
builder.registerTypeAdapterFactory(immutableList);
|
||||||
builder.registerTypeAdapterFactory(set);
|
builder.registerTypeAdapterFactory(set);
|
||||||
|
builder.registerTypeAdapterFactory(immutableSet);
|
||||||
builder.registerTypeAdapterFactory(map);
|
builder.registerTypeAdapterFactory(map);
|
||||||
builder.registerTypeAdapterFactory(multimap);
|
builder.registerTypeAdapterFactory(multimap);
|
||||||
builder.registerTypeAdapterFactory(fluentIterable);
|
builder.registerTypeAdapterFactory(fluentIterable);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -61,15 +62,73 @@ public class NullFilteringTypeAdapterFactories {
|
||||||
param));
|
param));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IterableTypeAdapterFactory implements TypeAdapterFactory {
|
public static final class IterableTypeAdapter<E> extends TypeAdapter<Iterable<E>> {
|
||||||
|
|
||||||
|
private final TypeAdapter<E> elementAdapter;
|
||||||
|
|
||||||
|
public IterableTypeAdapter(TypeAdapter<E> elementAdapter) {
|
||||||
|
this.elementAdapter = elementAdapter;
|
||||||
|
nullSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JsonWriter out, Iterable<E> value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.beginArray();
|
||||||
|
for (E element : value)
|
||||||
|
elementAdapter.write(out, element);
|
||||||
|
out.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<E> read(JsonReader in) throws IOException {
|
||||||
|
return readAndBuild(in, ImmutableList.<E> builder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <C extends Iterable<E>, B extends ImmutableCollection.Builder<E>> C readAndBuild(JsonReader in,
|
||||||
|
B builder) throws IOException {
|
||||||
|
in.beginArray();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
E element = elementAdapter.read(in);
|
||||||
|
if (element != null)
|
||||||
|
builder.add(element);
|
||||||
|
}
|
||||||
|
in.endArray();
|
||||||
|
return (C) builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return elementAdapter.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
IterableTypeAdapter<?> that = IterableTypeAdapter.class.cast(obj);
|
||||||
|
return equal(this.elementAdapter, that.elementAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toStringHelper(this).add("elementAdapter", elementAdapter).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImmutableListTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
|
|
||||||
protected final Class<?> declaring;
|
protected final Class<?> declaring;
|
||||||
|
|
||||||
public IterableTypeAdapterFactory() {
|
public ImmutableListTypeAdapterFactory() {
|
||||||
this(Iterable.class);
|
this(ImmutableList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IterableTypeAdapterFactory(Class<?> declaring) {
|
protected ImmutableListTypeAdapterFactory(Class<?> declaring) {
|
||||||
this.declaring = declaring;
|
this.declaring = declaring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,164 +147,124 @@ public class NullFilteringTypeAdapterFactories {
|
||||||
return (TypeAdapter<I>) new IterableTypeAdapter<E>(elementAdapter);
|
return (TypeAdapter<I>) new IterableTypeAdapter<E>(elementAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class IterableTypeAdapter<E> extends TypeAdapter<Iterable<E>> {
|
|
||||||
|
|
||||||
private final TypeAdapter<E> elementAdapter;
|
|
||||||
|
|
||||||
public IterableTypeAdapter(TypeAdapter<E> elementAdapter) {
|
|
||||||
this.elementAdapter = elementAdapter;
|
|
||||||
nullSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(JsonWriter out, Iterable<E> value) throws IOException {
|
|
||||||
if (value == null) {
|
|
||||||
out.nullValue();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.beginArray();
|
|
||||||
for (E element : value)
|
|
||||||
elementAdapter.write(out, element);
|
|
||||||
out.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterable<E> read(JsonReader in) throws IOException {
|
|
||||||
return readAndBuild(in, ImmutableList.<E> builder());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected <C extends Iterable<E>, B extends ImmutableCollection.Builder<E>> C readAndBuild(JsonReader in,
|
|
||||||
B builder) throws IOException {
|
|
||||||
in.beginArray();
|
|
||||||
while (in.hasNext()) {
|
|
||||||
E element = elementAdapter.read(in);
|
|
||||||
if (element != null)
|
|
||||||
builder.add(element);
|
|
||||||
}
|
|
||||||
in.endArray();
|
|
||||||
return (C) builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return elementAdapter.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
IterableTypeAdapter<?> that = IterableTypeAdapter.class.cast(obj);
|
|
||||||
return equal(this.elementAdapter, that.elementAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(this).add("elementAdapter", elementAdapter).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CollectionTypeAdapterFactory extends IterableTypeAdapterFactory {
|
public static class IterableTypeAdapterFactory extends ImmutableListTypeAdapterFactory {
|
||||||
|
public IterableTypeAdapterFactory() {
|
||||||
|
super(Iterable.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CollectionTypeAdapterFactory extends ImmutableListTypeAdapterFactory {
|
||||||
public CollectionTypeAdapterFactory() {
|
public CollectionTypeAdapterFactory() {
|
||||||
super(Collection.class);
|
super(Collection.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public static class ListTypeAdapterFactory extends ImmutableListTypeAdapterFactory {
|
||||||
protected <E, I> TypeAdapter<I> newAdapter(TypeAdapter<E> elementAdapter) {
|
public ListTypeAdapterFactory() {
|
||||||
return (TypeAdapter<I>) new CollectionTypeAdapter<E>(elementAdapter);
|
super(List.class);
|
||||||
}
|
|
||||||
|
|
||||||
public static final class CollectionTypeAdapter<E> extends TypeAdapter<Collection<E>> {
|
|
||||||
|
|
||||||
private final IterableTypeAdapterFactory.IterableTypeAdapter<E> delegate;
|
|
||||||
|
|
||||||
public CollectionTypeAdapter(TypeAdapter<E> elementAdapter) {
|
|
||||||
this.delegate = new IterableTypeAdapterFactory.IterableTypeAdapter<E>(elementAdapter);
|
|
||||||
nullSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(JsonWriter out, Collection<E> value) throws IOException {
|
|
||||||
this.delegate.write(out, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<E> read(JsonReader in) throws IOException {
|
|
||||||
return delegate.readAndBuild(in, ImmutableList.<E> builder());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return delegate.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
CollectionTypeAdapter<?> that = CollectionTypeAdapter.class.cast(obj);
|
|
||||||
return equal(this.delegate, that.delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(this).add("elementAdapter", delegate.elementAdapter).toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SetTypeAdapterFactory extends IterableTypeAdapterFactory {
|
public static final class SetTypeAdapter<E> extends TypeAdapter<Set<E>> {
|
||||||
public SetTypeAdapterFactory() {
|
|
||||||
super(Set.class);
|
private final IterableTypeAdapter<E> delegate;
|
||||||
|
|
||||||
|
public SetTypeAdapter(TypeAdapter<E> elementAdapter) {
|
||||||
|
this.delegate = new IterableTypeAdapter<E>(elementAdapter);
|
||||||
|
nullSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JsonWriter out, Set<E> value) throws IOException {
|
||||||
|
this.delegate.write(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<E> read(JsonReader in) throws IOException {
|
||||||
|
return delegate.readAndBuild(in, ImmutableSet.<E> builder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return delegate.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
SetTypeAdapter<?> that = SetTypeAdapter.class.cast(obj);
|
||||||
|
return equal(this.delegate, that.delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toStringHelper(this).add("elementAdapter", delegate.elementAdapter).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImmutableSetTypeAdapterFactory extends ImmutableListTypeAdapterFactory {
|
||||||
|
public ImmutableSetTypeAdapterFactory() {
|
||||||
|
this(ImmutableSet.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ImmutableSetTypeAdapterFactory(Class<?> declaring) {
|
||||||
|
super(declaring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <E, I> TypeAdapter<I> newAdapter(TypeAdapter<E> elementAdapter) {
|
protected <E, I> TypeAdapter<I> newAdapter(TypeAdapter<E> elementAdapter) {
|
||||||
return (TypeAdapter<I>) new SetTypeAdapter<E>(elementAdapter);
|
return (TypeAdapter<I>) new SetTypeAdapter<E>(elementAdapter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static final class SetTypeAdapter<E> extends TypeAdapter<Set<E>> {
|
public static class SetTypeAdapterFactory extends ImmutableSetTypeAdapterFactory {
|
||||||
|
public SetTypeAdapterFactory() {
|
||||||
private final IterableTypeAdapterFactory.IterableTypeAdapter<E> delegate;
|
super(Set.class);
|
||||||
|
|
||||||
public SetTypeAdapter(TypeAdapter<E> elementAdapter) {
|
|
||||||
this.delegate = new IterableTypeAdapterFactory.IterableTypeAdapter<E>(elementAdapter);
|
|
||||||
nullSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(JsonWriter out, Set<E> value) throws IOException {
|
|
||||||
this.delegate.write(out, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<E> read(JsonReader in) throws IOException {
|
|
||||||
return delegate.readAndBuild(in, ImmutableSet.<E> builder());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return delegate.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
SetTypeAdapter<?> that = SetTypeAdapter.class.cast(obj);
|
|
||||||
return equal(this.delegate, that.delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(this).add("elementAdapter", delegate.elementAdapter).toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FluentIterableTypeAdapterFactory extends IterableTypeAdapterFactory {
|
private static final class FluentIterableTypeAdapter<E> extends TypeAdapter<FluentIterable<E>> {
|
||||||
|
|
||||||
|
private final IterableTypeAdapter<E> delegate;
|
||||||
|
|
||||||
|
public FluentIterableTypeAdapter(TypeAdapter<E> elementAdapter) {
|
||||||
|
this.delegate = new IterableTypeAdapter<E>(elementAdapter);
|
||||||
|
nullSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JsonWriter out, FluentIterable<E> value) throws IOException {
|
||||||
|
this.delegate.write(out, value.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentIterable<E> read(JsonReader in) throws IOException {
|
||||||
|
return FluentIterable.from(delegate.read(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return delegate.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
FluentIterableTypeAdapter<?> that = FluentIterableTypeAdapter.class.cast(obj);
|
||||||
|
return equal(this.delegate, that.delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toStringHelper(this).add("elementAdapter", delegate.elementAdapter).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FluentIterableTypeAdapterFactory extends ImmutableListTypeAdapterFactory {
|
||||||
public FluentIterableTypeAdapterFactory() {
|
public FluentIterableTypeAdapterFactory() {
|
||||||
super(FluentIterable.class);
|
super(FluentIterable.class);
|
||||||
}
|
}
|
||||||
|
@ -254,43 +273,64 @@ public class NullFilteringTypeAdapterFactories {
|
||||||
protected <E, I> TypeAdapter<I> newAdapter(TypeAdapter<E> elementAdapter) {
|
protected <E, I> TypeAdapter<I> newAdapter(TypeAdapter<E> elementAdapter) {
|
||||||
return (TypeAdapter<I>) new FluentIterableTypeAdapter<E>(elementAdapter);
|
return (TypeAdapter<I>) new FluentIterableTypeAdapter<E>(elementAdapter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static final class FluentIterableTypeAdapter<E> extends TypeAdapter<FluentIterable<E>> {
|
private static final class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
|
||||||
|
|
||||||
private final IterableTypeAdapterFactory.IterableTypeAdapter<E> delegate;
|
protected final TypeAdapter<K> keyAdapter;
|
||||||
|
protected final TypeAdapter<V> valueAdapter;
|
||||||
|
|
||||||
public FluentIterableTypeAdapter(TypeAdapter<E> elementAdapter) {
|
protected MapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
||||||
this.delegate = new IterableTypeAdapterFactory.IterableTypeAdapter<E>(elementAdapter);
|
this.keyAdapter = keyAdapter;
|
||||||
nullSafe();
|
this.valueAdapter = valueAdapter;
|
||||||
|
nullSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(JsonWriter out, Map<K, V> value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
out.beginObject();
|
||||||
public void write(JsonWriter out, FluentIterable<E> value) throws IOException {
|
for (Map.Entry<K, V> element : value.entrySet()) {
|
||||||
this.delegate.write(out, value.toList());
|
out.name(String.valueOf(element.getKey()));
|
||||||
|
valueAdapter.write(out, element.getValue());
|
||||||
}
|
}
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
public FluentIterable<E> read(JsonReader in) throws IOException {
|
public Map<K, V> read(JsonReader in) throws IOException {
|
||||||
return FluentIterable.from(delegate.read(in));
|
ImmutableMap.Builder<K, V> result = ImmutableMap.builder();
|
||||||
|
in.beginObject();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
|
||||||
|
K name = keyAdapter.read(in);
|
||||||
|
V value = valueAdapter.read(in);
|
||||||
|
if (value != null)
|
||||||
|
result.put(name, value);
|
||||||
}
|
}
|
||||||
|
in.endObject();
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return delegate.hashCode();
|
return Objects.hashCode(keyAdapter, valueAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj)
|
||||||
return true;
|
return true;
|
||||||
if (obj == null || getClass() != obj.getClass())
|
if (obj == null || getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
FluentIterableTypeAdapter<?> that = FluentIterableTypeAdapter.class.cast(obj);
|
MapTypeAdapter<?, ?> that = MapTypeAdapter.class.cast(obj);
|
||||||
return equal(this.delegate, that.delegate);
|
return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toStringHelper(this).add("elementAdapter", delegate.elementAdapter).toString();
|
return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,64 +361,49 @@ public class NullFilteringTypeAdapterFactories {
|
||||||
protected <K, V, T> TypeAdapter<T> newAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
protected <K, V, T> TypeAdapter<T> newAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
||||||
return (TypeAdapter<T>) new MapTypeAdapter<K, V>(keyAdapter, valueAdapter);
|
return (TypeAdapter<T>) new MapTypeAdapter<K, V>(keyAdapter, valueAdapter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static final class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
|
private static final class MultimapTypeAdapter<K, V> extends TypeAdapter<Multimap<K, V>> {
|
||||||
|
|
||||||
protected final TypeAdapter<K> keyAdapter;
|
private final MapTypeAdapter<K, Iterable<V>> delegate;
|
||||||
protected final TypeAdapter<V> valueAdapter;
|
|
||||||
|
|
||||||
protected MapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
public MultimapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
||||||
this.keyAdapter = keyAdapter;
|
this.delegate = new MapTypeAdapter<K, Iterable<V>>(keyAdapter,
|
||||||
this.valueAdapter = valueAdapter;
|
new IterableTypeAdapter<V>(valueAdapter));
|
||||||
nullSafe();
|
nullSafe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(JsonWriter out, Map<K, V> value) throws IOException {
|
@SuppressWarnings("unchecked")
|
||||||
if (value == null) {
|
public void write(JsonWriter out, Multimap<K, V> value) throws IOException {
|
||||||
out.nullValue();
|
this.delegate.write(out, Map.class.cast(value.asMap()));
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
out.beginObject();
|
|
||||||
for (Map.Entry<K, V> element : value.entrySet()) {
|
|
||||||
out.name(String.valueOf(element.getKey()));
|
|
||||||
valueAdapter.write(out, element.getValue());
|
|
||||||
}
|
|
||||||
out.endObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<K, V> read(JsonReader in) throws IOException {
|
public Multimap<K, V> read(JsonReader in) throws IOException {
|
||||||
ImmutableMap.Builder<K, V> result = ImmutableMap.builder();
|
ImmutableMultimap.Builder<K, V> builder = ImmutableMultimap.<K, V> builder();
|
||||||
in.beginObject();
|
for (Entry<K, Iterable<V>> entry : delegate.read(in).entrySet())
|
||||||
while (in.hasNext()) {
|
builder.putAll(entry.getKey(), entry.getValue());
|
||||||
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
|
return builder.build();
|
||||||
K name = keyAdapter.read(in);
|
}
|
||||||
V value = valueAdapter.read(in);
|
|
||||||
if (value != null)
|
|
||||||
result.put(name, value);
|
|
||||||
}
|
|
||||||
in.endObject();
|
|
||||||
return result.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(keyAdapter, valueAdapter);
|
return delegate.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj)
|
||||||
return true;
|
return true;
|
||||||
if (obj == null || getClass() != obj.getClass())
|
if (obj == null || getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
MapTypeAdapter<?, ?> that = MapTypeAdapter.class.cast(obj);
|
MultimapTypeAdapter<?, ?> that = MultimapTypeAdapter.class.cast(obj);
|
||||||
return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter);
|
return equal(this.delegate, that.delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString();
|
return toStringHelper(this).add("keyAdapter", delegate.keyAdapter)
|
||||||
}
|
.add("valueAdapter", delegate.valueAdapter).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,47 +419,5 @@ public class NullFilteringTypeAdapterFactories {
|
||||||
return (TypeAdapter<T>) new MultimapTypeAdapter<K, V>(keyAdapter, valueAdapter);
|
return (TypeAdapter<T>) new MultimapTypeAdapter<K, V>(keyAdapter, valueAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class MultimapTypeAdapter<K, V> extends TypeAdapter<Multimap<K, V>> {
|
|
||||||
|
|
||||||
private final MapTypeAdapterFactory.MapTypeAdapter<K, Collection<V>> delegate;
|
|
||||||
|
|
||||||
public MultimapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
|
|
||||||
this.delegate = new MapTypeAdapterFactory.MapTypeAdapter<K, Collection<V>>(keyAdapter,
|
|
||||||
new CollectionTypeAdapterFactory.CollectionTypeAdapter<V>(valueAdapter));
|
|
||||||
nullSafe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(JsonWriter out, Multimap<K, V> value) throws IOException {
|
|
||||||
this.delegate.write(out, value.asMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Multimap<K, V> read(JsonReader in) throws IOException {
|
|
||||||
ImmutableMultimap.Builder<K, V> builder = ImmutableMultimap.<K, V> builder();
|
|
||||||
for (Entry<K, Collection<V>> entry : delegate.read(in).entrySet())
|
|
||||||
builder.putAll(entry.getKey(), entry.getValue());
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return delegate.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
MultimapTypeAdapter<?, ?> that = MultimapTypeAdapter.class.cast(obj);
|
|
||||||
return equal(this.delegate, that.delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(this).add("keyAdapter", delegate.keyAdapter)
|
|
||||||
.add("valueAdapter", delegate.valueAdapter).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,16 @@ import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.CollectionTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.CollectionTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.FluentIterableTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.FluentIterableTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ImmutableListTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ImmutableSetTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.IterableTypeAdapterFactory;
|
||||||
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ListTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MultimapTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MultimapTypeAdapterFactory;
|
||||||
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapterFactory;
|
||||||
|
@ -149,6 +153,46 @@ public class NullFilteringTypeAdapterFactoriesTest {
|
||||||
ImmutableList.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
ImmutableList.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Gson list = new GsonBuilder().registerTypeAdapterFactory(new ListTypeAdapterFactory()).create();
|
||||||
|
private Type listType = new TypeToken<List<String>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
private Type listResourceType = new TypeToken<List<Resource>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
public void testList() {
|
||||||
|
Iterable<String> noNulls = list.fromJson("[\"value\",\"a test string!\"]", listType);
|
||||||
|
assertEquals(noNulls, ImmutableList.of("value", "a test string!"));
|
||||||
|
Iterable<String> withNull = list.fromJson("[null,\"a test string!\"]", listType);
|
||||||
|
assertEquals(withNull, ImmutableList.of("a test string!"));
|
||||||
|
Iterable<String> withDupes = list.fromJson("[\"value\",\"value\"]", listType);
|
||||||
|
assertEquals(withDupes, ImmutableList.of("value", "value"));
|
||||||
|
Iterable<Resource> resources = list.fromJson(
|
||||||
|
"[{\"id\":\"i-foo\",\"name\":\"foo\"},{\"id\":\"i-bar\",\"name\":\"bar\"}]", listResourceType);
|
||||||
|
assertEquals(resources, ImmutableList.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gson immutableList = new GsonBuilder().registerTypeAdapterFactory(new ImmutableListTypeAdapterFactory()).create();
|
||||||
|
private Type immutableListType = new TypeToken<ImmutableList<String>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
private Type immutableListResourceType = new TypeToken<ImmutableList<Resource>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
public void testImmutableList() {
|
||||||
|
Iterable<String> noNulls = immutableList.fromJson("[\"value\",\"a test string!\"]", immutableListType);
|
||||||
|
assertEquals(noNulls, ImmutableList.of("value", "a test string!"));
|
||||||
|
Iterable<String> withNull = immutableList.fromJson("[null,\"a test string!\"]", immutableListType);
|
||||||
|
assertEquals(withNull, ImmutableList.of("a test string!"));
|
||||||
|
Iterable<String> withDupes = immutableList.fromJson("[\"value\",\"value\"]", immutableListType);
|
||||||
|
assertEquals(withDupes, ImmutableList.of("value", "value"));
|
||||||
|
Iterable<Resource> resources = immutableList.fromJson(
|
||||||
|
"[{\"id\":\"i-foo\",\"name\":\"foo\"},{\"id\":\"i-bar\",\"name\":\"bar\"}]", immutableListResourceType);
|
||||||
|
assertEquals(resources, ImmutableList.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
||||||
|
}
|
||||||
|
|
||||||
private Gson set = new GsonBuilder().registerTypeAdapterFactory(new SetTypeAdapterFactory()).create();
|
private Gson set = new GsonBuilder().registerTypeAdapterFactory(new SetTypeAdapterFactory()).create();
|
||||||
private Type setType = new TypeToken<Set<String>>() {
|
private Type setType = new TypeToken<Set<String>>() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -169,6 +213,26 @@ public class NullFilteringTypeAdapterFactoriesTest {
|
||||||
assertEquals(resources, ImmutableSet.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
assertEquals(resources, ImmutableSet.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Gson immutableSet = new GsonBuilder().registerTypeAdapterFactory(new ImmutableSetTypeAdapterFactory()).create();
|
||||||
|
private Type immutableSetType = new TypeToken<ImmutableSet<String>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
private Type immutableSetResourceType = new TypeToken<ImmutableSet<Resource>>() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
public void testImmutableSet() {
|
||||||
|
Iterable<String> noNulls = immutableSet.fromJson("[\"value\",\"a test string!\"]", immutableSetType);
|
||||||
|
assertEquals(noNulls, ImmutableSet.of("value", "a test string!"));
|
||||||
|
Iterable<String> withNull = immutableSet.fromJson("[null,\"a test string!\"]", immutableSetType);
|
||||||
|
assertEquals(withNull, ImmutableSet.of("a test string!"));
|
||||||
|
Iterable<String> withDupes = immutableSet.fromJson("[\"value\",\"value\"]", immutableSetType);
|
||||||
|
assertEquals(withDupes, ImmutableSet.of("value", "value"));
|
||||||
|
Iterable<Resource> resources = immutableSet.fromJson(
|
||||||
|
"[{\"id\":\"i-foo\",\"name\":\"foo\"},{\"id\":\"i-bar\",\"name\":\"bar\"}]", immutableSetResourceType);
|
||||||
|
assertEquals(resources, ImmutableSet.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
|
||||||
|
}
|
||||||
|
|
||||||
private Gson map = new GsonBuilder().registerTypeAdapterFactory(new MapTypeAdapterFactory()).create();
|
private Gson map = new GsonBuilder().registerTypeAdapterFactory(new MapTypeAdapterFactory()).create();
|
||||||
private Type mapType = new TypeToken<Map<String, String>>() {
|
private Type mapType = new TypeToken<Map<String, String>>() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
Loading…
Reference in New Issue