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");