You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/10/26 20:31:19 UTC
[3/4] git commit: JCLOUDS-750 allow apis to bind FieldNamingPolicy,
which controls fallback naming policy of serialized fields.
JCLOUDS-750 allow apis to bind FieldNamingPolicy, which controls fallback naming policy of serialized fields.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/5b6f1e92
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/5b6f1e92
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/5b6f1e92
Branch: refs/heads/master
Commit: 5b6f1e929ef4b6438facc06df0f081ddef8c9cf6
Parents: 0b88dad
Author: Adrian Cole <ad...@gmail.com>
Authored: Sun Oct 26 10:22:48 2014 -0700
Committer: Adrian Cole <ad...@gmail.com>
Committed: Sun Oct 26 12:31:06 2014 -0700
----------------------------------------------------------------------
.../org/jclouds/json/config/GsonModule.java | 17 ++++--
.../jclouds/json/internal/NamingStrategies.java | 14 +++--
.../test/java/org/jclouds/json/JsonTest.java | 64 ++++++++++++++++++++
...ctorAndReflectiveTypeAdapterFactoryTest.java | 3 +-
.../json/internal/NamingStrategiesTest.java | 12 ++--
5 files changed, 94 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/5b6f1e92/core/src/main/java/org/jclouds/json/config/GsonModule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/json/config/GsonModule.java b/core/src/main/java/org/jclouds/json/config/GsonModule.java
index afbed11..9aebbe9 100644
--- a/core/src/main/java/org/jclouds/json/config/GsonModule.java
+++ b/core/src/main/java/org/jclouds/json/config/GsonModule.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Sets;
import com.google.common.primitives.Bytes;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
+import com.google.gson.FieldNamingPolicy;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -38,6 +39,7 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
+import com.google.inject.Inject;
import com.google.inject.Provides;
import org.jclouds.date.DateService;
import org.jclouds.domain.JsonBall;
@@ -63,7 +65,6 @@ import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.SetTypeAdapte
import org.jclouds.json.internal.NullHackJsonLiteralAdapter;
import org.jclouds.json.internal.OptionalTypeAdapterFactory;
-import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.beans.ConstructorProperties;
@@ -78,11 +79,14 @@ import java.util.Set;
import static com.google.common.io.BaseEncoding.base16;
-/**
- * Contains logic for parsing objects from Strings.
- */
public class GsonModule extends AbstractModule {
+ /** Optionally override the fallback policy when name annotations aren't on fields. */
+ private static class FallbackFieldNamingPolicy {
+ @Inject(optional = true)
+ FieldNamingPolicy fallback = FieldNamingPolicy.IDENTITY;
+ }
+
@SuppressWarnings("rawtypes")
@Provides
@Singleton
@@ -92,10 +96,11 @@ public class GsonModule extends AbstractModule {
MapTypeAdapterFactory map, MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
CollectionTypeAdapterFactory collection, ListTypeAdapterFactory list,
ImmutableListTypeAdapterFactory immutableList, FluentIterableTypeAdapterFactory fluentIterable,
- ImmutableMapTypeAdapterFactory immutableMap, DefaultExclusionStrategy exclusionStrategy) {
+ ImmutableMapTypeAdapterFactory immutableMap, DefaultExclusionStrategy exclusionStrategy,
+ FallbackFieldNamingPolicy fallbackFieldNamingPolicy) {
FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(
- new ExtractSerializedName(), new ExtractNamed()));
+ new ExtractSerializedName(), new ExtractNamed()), fallbackFieldNamingPolicy.fallback);
GsonBuilder builder = new GsonBuilder().setFieldNamingStrategy(serializationPolicy)
.setExclusionStrategies(exclusionStrategy);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/5b6f1e92/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java b/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java
index 7a94ce3..c3931a1 100644
--- a/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java
+++ b/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java
@@ -43,6 +43,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.Maps;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
+import com.google.gson.FieldNamingPolicy;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.annotations.SerializedName;
@@ -162,10 +163,14 @@ public class NamingStrategies {
public static class AnnotationFieldNamingStrategy extends AnnotationBasedNamingStrategy implements
FieldNamingStrategy {
- public AnnotationFieldNamingStrategy(Iterable<? extends NameExtractor<?>> extractors) {
+ private final FieldNamingPolicy fallback;
+
+ public AnnotationFieldNamingStrategy(Iterable<? extends NameExtractor<?>> extractors,
+ FieldNamingPolicy fallback) {
super(extractors);
checkArgument(extractors.iterator().hasNext(), "you must supply at least one name extractor, for example: "
+ ExtractSerializedName.class.getSimpleName());
+ this.fallback = checkNotNull(fallback, "fallback fieldNamingPolicy");
}
@Override
@@ -175,15 +180,16 @@ public class NamingStrategies {
return annotationToNameExtractor.get(annotation.annotationType()).apply(annotation);
}
}
- return null;
+ return fallback.translateName(f);
}
}
public static class AnnotationOrNameFieldNamingStrategy extends AnnotationFieldNamingStrategy implements
FieldNamingStrategy {
- public AnnotationOrNameFieldNamingStrategy(Iterable<? extends NameExtractor<?>> extractors) {
- super(extractors);
+ public AnnotationOrNameFieldNamingStrategy(Iterable<? extends NameExtractor<?>> extractors,
+ FieldNamingPolicy fallback) {
+ super(extractors, fallback);
}
@Override
http://git-wip-us.apache.org/repos/asf/jclouds/blob/5b6f1e92/core/src/test/java/org/jclouds/json/JsonTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/json/JsonTest.java b/core/src/test/java/org/jclouds/json/JsonTest.java
index 3dd5584..ed32220 100644
--- a/core/src/test/java/org/jclouds/json/JsonTest.java
+++ b/core/src/test/java/org/jclouds/json/JsonTest.java
@@ -31,6 +31,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.FieldAttributes;
+import com.google.gson.FieldNamingPolicy;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.TypeLiteral;
@@ -209,4 +210,67 @@ public class JsonTest {
EnumInsideWithParser.Test.UNRECOGNIZED);
}
+ private abstract static class SpinalCasedType {
+ abstract String id();
+
+ abstract String contentType();
+
+ // Currently, this only works for deserialization. Need to set a naming policy for serialization!
+ @SerializedNames({ "id", "content-type" })
+ private static SpinalCasedType create(String id, String contentType) {
+ return new SpinalCasedTypeImpl(id, contentType);
+ }
+ }
+
+ public void spinalCaseWithSerializedNames() {
+ Json json = Guice.createInjector(new GsonModule(), new AbstractModule() {
+ @Override protected void configure() {
+ bind(FieldNamingPolicy.class).toInstance(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);
+ }
+ }).getInstance(Json.class);
+
+ SpinalCasedType resource = SpinalCasedType.create("1234", "application/json");
+ String spinalJson = "{\"id\":\"1234\",\"content-type\":\"application/json\"}";
+
+ assertEquals(json.toJson(resource), spinalJson);
+ assertEquals(spinalJson, json.toJson(resource));
+ }
+
+ private static class SpinalCasedTypeImpl extends SpinalCasedType {
+ private final String id;
+ private final String contentType;
+
+ private SpinalCasedTypeImpl(String id, String contentType) {
+ this.id = id;
+ this.contentType = contentType;
+ }
+
+ @Override String id() {
+ return id;
+ }
+
+ @Override String contentType() {
+ return contentType;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof SpinalCasedType) {
+ SpinalCasedType that = (SpinalCasedType) o;
+ return (this.id.equals(that.id())) && (this.contentType.equals(that.contentType()));
+ }
+ return false;
+ }
+
+ @Override public int hashCode() {
+ int h = 1;
+ h *= 1000003;
+ h ^= id.hashCode();
+ h *= 1000003;
+ h ^= contentType.hashCode();
+ return h;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/5b6f1e92/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java b/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java
index 1d54d09..b4f0202 100644
--- a/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java
+++ b/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java
@@ -43,6 +43,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.gson.FieldNamingPolicy;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -62,7 +63,7 @@ public final class DeserializationConstructorAndReflectiveTypeAdapterFactoryTest
static DeserializationConstructorAndReflectiveTypeAdapterFactory parameterizedCtorFactory() {
FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(
- new ExtractSerializedName(), new ExtractNamed()));
+ new ExtractSerializedName(), new ExtractNamed()), FieldNamingPolicy.IDENTITY);
AnnotationConstructorNamingStrategy deserializationPolicy = new AnnotationConstructorNamingStrategy(
ImmutableSet.of(ConstructorProperties.class, SerializedNames.class, Inject.class),
ImmutableSet.of(new ExtractNamed()));
http://git-wip-us.apache.org/repos/asf/jclouds/blob/5b6f1e92/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java b/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java
index ccd947a..20c6046 100644
--- a/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java
+++ b/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java
@@ -19,7 +19,6 @@ package org.jclouds.json.internal;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
import static org.testng.Assert.fail;
import java.beans.ConstructorProperties;
@@ -37,6 +36,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.Invokable;
+import com.google.gson.FieldNamingPolicy;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.annotations.SerializedName;
@@ -101,16 +101,18 @@ public final class NamingStrategiesTest {
}
public void testAnnotationFieldNamingStrategy() throws Exception {
- FieldNamingStrategy strategy = new AnnotationFieldNamingStrategy(ImmutableSet.of(new ExtractNamed()));
+ FieldNamingStrategy strategy = new AnnotationFieldNamingStrategy(ImmutableSet.of(new ExtractNamed()),
+ FieldNamingPolicy.UPPER_CAMEL_CASE);
- assertNull(strategy.translateName(SimpleTest.class.getDeclaredField("a")));
- assertNull(strategy.translateName(SimpleTest.class.getDeclaredField("b")));
+ assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("a")), "A"); // Per fallback!
+ assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("b")), "B"); // Per fallback!
assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("c")), "cat");
assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("d")), "dog");
}
public void testAnnotationOrNameFieldNamingStrategy() throws Exception {
- FieldNamingStrategy strategy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(new ExtractNamed()));
+ FieldNamingStrategy strategy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(new ExtractNamed()),
+ FieldNamingPolicy.IDENTITY);
assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("a")), "a");
assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("b")), "b");