summaryrefslogtreecommitdiffstats
path: root/gson
diff options
context:
space:
mode:
authorLiam Fallon <liam.fallon@est.tech>2019-02-13 13:43:21 +0000
committerGerrit Code Review <gerrit@onap.org>2019-02-13 13:43:21 +0000
commit15fc9d176360a6cc2f7e7c49b96fdf4142d48159 (patch)
treef85e98471be1b215f2409fb08aee4f2877a9e506 /gson
parent5ddd8900f821d43ab4710309da72cf71cda9c805 (diff)
parent3cc17f964e46578f8ff6275072d1c77dafa551dd (diff)
Merge "Add jackson behavior for methods"
Diffstat (limited to 'gson')
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/JacksonMethodAdapterFactory.java202
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/Adapter.java7
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/AnyGetterSerializer.java83
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/AnySetterDeserializer.java58
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/Lifter.java62
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/MethodAdapter.java69
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/MethodDeserializer.java53
-rw-r--r--gson/src/main/java/org/onap/policy/common/gson/internal/MethodSerializer.java47
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/JacksonMethodAdapterFactoryTest.java311
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/AdapterTest.java8
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/AnyGetterSerializerTest.java134
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/AnySetterDeserializerTest.java94
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/LifterTest.java55
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/MethodAdapterTest.java58
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/MethodDeserializerTest.java100
-rw-r--r--gson/src/test/java/org/onap/policy/common/gson/internal/MethodSerializerTest.java88
16 files changed, 1421 insertions, 8 deletions
diff --git a/gson/src/main/java/org/onap/policy/common/gson/JacksonMethodAdapterFactory.java b/gson/src/main/java/org/onap/policy/common/gson/JacksonMethodAdapterFactory.java
new file mode 100644
index 00000000..1c3039f7
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/JacksonMethodAdapterFactory.java
@@ -0,0 +1,202 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+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.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.onap.policy.common.gson.internal.AnyGetterSerializer;
+import org.onap.policy.common.gson.internal.AnySetterDeserializer;
+import org.onap.policy.common.gson.internal.ClassWalker;
+import org.onap.policy.common.gson.internal.Deserializer;
+import org.onap.policy.common.gson.internal.MethodDeserializer;
+import org.onap.policy.common.gson.internal.MethodSerializer;
+import org.onap.policy.common.gson.internal.Serializer;
+
+/**
+ * Factory that serializes/deserializes class methods following the normal behavior of
+ * jackson. Supports the following annotations:
+ * <ul>
+ * <li>GsonJsonIgnore</li>
+ * <li>GsonJsonProperty</li>
+ * <li>GsonJsonAnyGetter</li>
+ * <li>GsonJsonAnySetter</li>
+ * </ul>
+ */
+public class JacksonMethodAdapterFactory implements TypeAdapterFactory {
+
+ @Override
+ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
+ Class<? super T> clazz = type.getRawType();
+
+ if (!JacksonExclusionStrategy.isManaged(clazz)) {
+ return null;
+ }
+
+ ClassWalker data = new ClassWalker();
+ data.walkClassHierarchy(clazz);
+
+ if (data.getInProps(Method.class).isEmpty() && data.getOutProps(Method.class).isEmpty()) {
+ if (data.getAnyGetter() == null && data.getAnySetter() == null) {
+ // no methods to serialize
+ return null;
+ }
+ }
+
+ return new JacksonMethodAdapter<>(gson, data, gson.getDelegateAdapter(this, type));
+ }
+
+ /**
+ * Adapter for a single class.
+ *
+ * @param <T> type of class on which the adapter works
+ */
+ private static class JacksonMethodAdapter<T> extends TypeAdapter<T> {
+
+ /**
+ * Used to create an object of the given class.
+ */
+ private final TypeAdapter<T> delegate;
+
+ /**
+ * Used to serialize/deserialize a JsonElement.
+ */
+ private final TypeAdapter<JsonElement> elementAdapter;
+
+ /**
+ * Serializers for each item within the object.
+ */
+ private final Serializer[] serializers;
+
+ /**
+ * Deserializers for each item within the object.
+ */
+ private final Deserializer[] deserializers;
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson the associated gson object
+ * @param data data used to configure the adapter
+ * @param delegate default constructor for the type
+ */
+ public JacksonMethodAdapter(Gson gson, ClassWalker data, TypeAdapter<T> delegate) {
+ this.delegate = delegate;
+
+ this.elementAdapter = gson.getAdapter(JsonElement.class);
+
+ Set<String> unliftedProps = new HashSet<>();
+ unliftedProps.addAll(data.getInNotIgnored());
+ unliftedProps.addAll(data.getOutNotIgnored());
+
+ // create serializers
+ this.serializers = makeSerializers(gson, data, unliftedProps).toArray(new Serializer[0]);
+
+ // create deserializers
+ this.deserializers = makeDeserializers(gson, data, unliftedProps).toArray(new Deserializer[0]);
+ }
+
+ /**
+ * Creates a complete list of serializers.
+ *
+ * @param gson the associated gson object
+ * @param data data used to configure the serializers
+ * @param unliftedProps properties that should not be lowered by "any-getters"
+ * @return a list of all serializers
+ */
+ private List<Serializer> makeSerializers(Gson gson, ClassWalker data, Set<String> unliftedProps) {
+ List<Serializer> ser = new ArrayList<Serializer>();
+
+ if (data.getAnyGetter() != null) {
+ ser.add(new AnyGetterSerializer(gson, unliftedProps, data.getAnyGetter()));
+ }
+
+ data.getOutProps(Method.class).forEach(method -> ser.add(new MethodSerializer(gson, method)));
+
+ return ser;
+ }
+
+ /**
+ * Creates a complete list of deserializers.
+ *
+ * @param gson the associated gson object
+ * @param data data used to configure the deserializers
+ * @param unliftedProps properties that should not be lifted by "any-setters"
+ * @return a list of all deserializers
+ */
+ private List<Deserializer> makeDeserializers(Gson gson, ClassWalker data, Set<String> unliftedProps) {
+ List<Deserializer> deser = new ArrayList<Deserializer>();
+
+ if (data.getAnySetter() != null) {
+ deser.add(new AnySetterDeserializer(gson, unliftedProps, data.getAnySetter()));
+ }
+
+ data.getInProps(Method.class).forEach(method -> deser.add(new MethodDeserializer(gson, method)));
+
+ return deser;
+ }
+
+ @Override
+ public void write(JsonWriter out, T value) throws IOException {
+ JsonElement tree = delegate.toJsonTree(value);
+
+ if (tree.isJsonObject()) {
+ JsonObject jsonObj = tree.getAsJsonObject();
+
+ // serialize each item from the value into the target tree
+ for (Serializer serializer : serializers) {
+ serializer.addToTree(value, jsonObj);
+ }
+ }
+
+ elementAdapter.write(out, tree);
+ }
+
+ @Override
+ public T read(JsonReader in) throws IOException {
+ JsonElement tree = elementAdapter.read(in);
+
+ T object = delegate.fromJsonTree(tree);
+
+ if (tree.isJsonObject()) {
+ JsonObject jsonObj = tree.getAsJsonObject();
+
+ // deserialize each item from the tree into the target object
+ for (Deserializer dser : deserializers) {
+ dser.getFromTree(jsonObj, object);
+ }
+ }
+
+ return object;
+ }
+ }
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/Adapter.java b/gson/src/main/java/org/onap/policy/common/gson/internal/Adapter.java
index b4ef53f7..bb8672bb 100644
--- a/gson/src/main/java/org/onap/policy/common/gson/internal/Adapter.java
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/Adapter.java
@@ -86,12 +86,11 @@ public class Adapter {
*
* @param gson Gson object providing type adapters
* @param accessor method used to access the item from within an object
- * @param forGetter {@code true} if the name is for a "getter" method, {@code false}
- * if for a "setter"
* @param valueType the class of value on which this operates
*/
- public Adapter(Gson gson, Method accessor, boolean forGetter, Type valueType) {
- this.propName = (forGetter ? detmGetterPropName(accessor) : detmSetterPropName(accessor));
+ public Adapter(Gson gson, Method accessor, Type valueType) {
+ boolean forSetter = (accessor.getReturnType() == void.class);
+ this.propName = (forSetter ? detmSetterPropName(accessor) : detmGetterPropName(accessor));
this.reader = new ConvInfo(TypeToken.get(valueType));
this.gson = gson;
this.fullName = getQualifiedName(accessor);
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/AnyGetterSerializer.java b/gson/src/main/java/org/onap/policy/common/gson/internal/AnyGetterSerializer.java
new file mode 100644
index 00000000..da9ad173
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/AnyGetterSerializer.java
@@ -0,0 +1,83 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.lang.reflect.Method;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Serializer for methods having a JsonAnyGetter annotation.
+ */
+public class AnyGetterSerializer extends Lifter implements Serializer {
+
+ public static final String NOT_AN_OBJECT_ERR = "expecting a JsonObject for ";
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param propName property name associated with the lifted field
+ * @param unliftedProps property names that should not be lifted
+ * @param getter method used to get the item from within an object
+ */
+ public AnyGetterSerializer(Gson gson, Set<String> unliftedProps, Method getter) {
+ super(gson, unliftedProps, getter, getter.getGenericReturnType());
+ }
+
+ @Override
+ public void addToTree(Object source, JsonObject target) {
+ // get the value from the object
+ Object value = invoke(source);
+ if (value == null) {
+ // nothing to lift
+ return;
+ }
+
+ JsonElement inner = toJsonTree(value);
+ if (!inner.isJsonObject()) {
+ throw new JsonParseException(makeError(NOT_AN_OBJECT_ERR));
+ }
+
+ // lift items from inner into the target
+ copyLiftedItems(inner.getAsJsonObject(), target);
+ }
+
+ /**
+ * Copies lifted items from one tree into another, without removing them from the
+ * source tree.
+ *
+ * @param source tree from which items are to be copied
+ * @param target tree into which items are to be copied
+ */
+ private void copyLiftedItems(JsonObject source, JsonObject target) {
+ for (Entry<String, JsonElement> ent : source.entrySet()) {
+ String name = ent.getKey();
+ if (shouldLift(name)) {
+ target.add(name, ent.getValue());
+ }
+ }
+ }
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/AnySetterDeserializer.java b/gson/src/main/java/org/onap/policy/common/gson/internal/AnySetterDeserializer.java
new file mode 100644
index 00000000..85d42dfa
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/AnySetterDeserializer.java
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.lang.reflect.Method;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * De-serializer for methods having a JsonAnySetter annotation.
+ */
+public class AnySetterDeserializer extends Lifter implements Deserializer {
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param unliftedProps property names that should not be lifted
+ * @param getter method used to get the item from within an object
+ */
+ public AnySetterDeserializer(Gson gson, Set<String> unliftedProps, Method setter) {
+ super(gson, unliftedProps, setter, setter.getGenericParameterTypes()[1]);
+ }
+
+ @Override
+ public void getFromTree(JsonObject source, Object target) {
+ for (Entry<String, JsonElement> ent : source.entrySet()) {
+ String name = ent.getKey();
+
+ if (shouldLift(name)) {
+ Object value = fromJsonTree(ent.getValue());
+ invoke(target, name, value);
+ }
+ }
+ }
+
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/Lifter.java b/gson/src/main/java/org/onap/policy/common/gson/internal/Lifter.java
new file mode 100644
index 00000000..bb8ec321
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/Lifter.java
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+/**
+ * Super class of serializers and de-serializers that deal with "lifted" data, that is,
+ * data that is lifted from a nested json object into the containing object.
+ */
+public class Lifter extends MethodAdapter {
+
+ /**
+ * Names of the properties that are <i>not</i> to be lifted.
+ */
+ private final Set<String> unliftedProps;
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param unliftedProps property names that should not be lifted
+ * @param accessor method used to access the item from within an object
+ * @param type the class of value on which this operates
+ */
+ public Lifter(Gson gson, Set<String> unliftedProps, Method accessor, Type type) {
+ super(gson, accessor, type);
+
+ this.unliftedProps = unliftedProps;
+ }
+
+ /**
+ * Determines if a property should be lifted.
+ *
+ * @param propName the name of the property
+ * @return {@code true} if the property should be lifted, {@code false} otherwise
+ */
+ public boolean shouldLift(String propName) {
+ return !unliftedProps.contains(propName);
+ }
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/MethodAdapter.java b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodAdapter.java
new file mode 100644
index 00000000..579864da
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * Super class of adapters used to serialize and de-serialize a method.
+ */
+public class MethodAdapter extends Adapter {
+
+ public static final String INVOKE_ERR = "cannot invoke method to serialize/deserialize: ";
+
+ /**
+ * Method used to access the item within an object.
+ */
+ private final Method accessor;
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param accessor method used to access the item from within an object
+ * @param type the class of value on which this operates
+ */
+ public MethodAdapter(Gson gson, Method accessor, Type type) {
+ super(gson, accessor, type);
+
+ this.accessor = accessor;
+ }
+
+ /**
+ * Invokes the accessor method.
+ *
+ * @param self object on which to invoke the method
+ * @param args arguments to be passed to the method
+ * @return the method's result
+ */
+ public Object invoke(Object self, Object... args) {
+ try {
+ return accessor.invoke(self, args);
+
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new JsonParseException(makeError(INVOKE_ERR), e);
+ }
+ }
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/MethodDeserializer.java b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodDeserializer.java
new file mode 100644
index 00000000..bb0724eb
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodDeserializer.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.lang.reflect.Method;
+
+/**
+ * De-serializer for methods that are exposed.
+ */
+public class MethodDeserializer extends MethodAdapter implements Deserializer {
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param setter method used to set the item within an object
+ */
+ public MethodDeserializer(Gson gson, Method setter) {
+ super(gson, setter, setter.getGenericParameterTypes()[0]);
+ }
+
+ @Override
+ public void getFromTree(JsonObject source, Object target) {
+ JsonElement jsonEl = source.get(getPropName());
+ if (jsonEl == null || jsonEl.isJsonNull()) {
+ return;
+ }
+
+ invoke(target, fromJsonTree(jsonEl));
+ }
+
+}
diff --git a/gson/src/main/java/org/onap/policy/common/gson/internal/MethodSerializer.java b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodSerializer.java
new file mode 100644
index 00000000..ab544614
--- /dev/null
+++ b/gson/src/main/java/org/onap/policy/common/gson/internal/MethodSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.lang.reflect.Method;
+
+/**
+ * Serializer for methods that are exposed.
+ */
+public class MethodSerializer extends MethodAdapter implements Serializer {
+
+ /**
+ * Constructs the object.
+ *
+ * @param gson Gson object providing type adapters
+ * @param getter method used to get the item from within an object
+ */
+ public MethodSerializer(Gson gson, Method getter) {
+ super(gson, getter, getter.getGenericReturnType());
+ }
+
+ @Override
+ public void addToTree(Object source, JsonObject target) {
+ Object value = invoke(source);
+ target.add(getPropName(), (value == null ? null : toJsonTree(value)));
+ }
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/JacksonMethodAdapterFactoryTest.java b/gson/src/test/java/org/onap/policy/common/gson/JacksonMethodAdapterFactoryTest.java
new file mode 100644
index 00000000..47cf4b3b
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/JacksonMethodAdapterFactoryTest.java
@@ -0,0 +1,311 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+import java.util.Map;
+import java.util.TreeMap;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonExclusionStrategy;
+import org.onap.policy.common.gson.JacksonMethodAdapterFactory;
+import org.onap.policy.common.gson.annotation.GsonJsonAnyGetter;
+import org.onap.policy.common.gson.annotation.GsonJsonAnySetter;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.common.gson.annotation.GsonJsonProperty;
+
+public class JacksonMethodAdapterFactoryTest {
+
+ private static JacksonMethodAdapterFactory factory = new JacksonMethodAdapterFactory();
+
+ private static Gson gson = new GsonBuilder().setExclusionStrategies(new JacksonExclusionStrategy())
+ .registerTypeAdapterFactory(factory).create();
+
+ @Test
+ public void testCreate() {
+ // unhandled types
+ assertNull(factory.create(gson, TypeToken.get(JsonElement.class)));
+ assertNull(factory.create(gson, TypeToken.get(NothingToSerialize.class)));
+
+ assertNotNull(factory.create(gson, TypeToken.get(Data.class)));
+ assertNotNull(factory.create(gson, TypeToken.get(Derived.class)));
+ assertNotNull(factory.create(gson, TypeToken.get(OnlyGetters.class)));
+ assertNotNull(factory.create(gson, TypeToken.get(OnlySetters.class)));
+ assertNotNull(factory.create(gson, TypeToken.get(OnlyAnyGetter.class)));
+ assertNotNull(factory.create(gson, TypeToken.get(OnlyAnySetter.class)));
+
+ // unhandled type
+
+ Data data = new Data();
+ data.id = 10;
+ data.text = "some text";
+
+ String result = gson.toJson(data);
+ Data data2 = gson.fromJson(result, Data.class);
+ assertEquals(data.toString(), data2.toString());
+
+ Derived der = new Derived();
+ der.setId(20);
+ der.setText("hello");
+ der.text = "world";
+ der.map = new TreeMap<>();
+ der.map.put("mapA", "valA");
+ der.map.put("mapB", "valB");
+
+ result = gson.toJson(der);
+
+ // should not contain the unserialized fields
+ assertFalse(result.contains("hello"));
+ assertFalse(result.contains("world"));
+
+ // null out unserialized fields
+ der.text = null;
+
+ // null out overridden field
+ der.setText(null);
+
+ Derived der2 = gson.fromJson(result, Derived.class);
+
+ assertEquals(der.toString(), der2.toString());
+
+ // override of AnyGetter
+ AnyGetterOverride dblget = new AnyGetterOverride();
+ dblget.setMap(der.map);
+ dblget.overMap = new TreeMap<>();
+ dblget.overMap.put("getA", 100);
+ dblget.overMap.put("getB", 110);
+
+ String result2 = gson.toJson(dblget);
+ dblget.overMap.keySet().forEach(key -> assertTrue("over contains " + key, result2.contains(key)));
+ der.map.keySet().forEach(key -> assertFalse("sub contains " + key, result2.contains(key)));
+
+ // override of AnySetter
+ Map<String, Integer> map = new TreeMap<>();
+ map.put("setA", 200);
+ map.put("setB", 210);
+ AnySetterOverride dblset = gson.fromJson(gson.toJson(map), AnySetterOverride.class);
+ assertEquals(map.toString(), dblset.overMap.toString());
+ assertNull(dblset.getTheMap());
+
+ // non-static nested class - can serialize, but not de-serialize
+ Container cont = new Container(500, "bye bye");
+ result = gson.toJson(cont);
+ assertEquals("{'id':500,'nested':{'value':'bye bye'}}".replace('\'', '"'), result);
+ }
+
+ protected static class Data {
+ private int id;
+ private String text;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ // not public, but property provided
+ @GsonJsonProperty("text")
+ protected String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public void unused(String text) {
+ // do nothing
+ }
+
+ @Override
+ public String toString() {
+ return "Data [id=" + id + ", text=" + text + "]";
+ }
+ }
+
+ protected static class Derived extends Data {
+
+ // overrides private field from Data
+ public String text;
+
+ private Map<String, String> map;
+
+ @GsonJsonAnyGetter
+ public Map<String, String> getTheMap() {
+ return map;
+ }
+
+ @GsonJsonIgnore
+ public void setMap(Map<String, String> map) {
+ this.map = map;
+ }
+
+ @GsonJsonAnySetter
+ public void setMapValue(String key, String value) {
+ if (map == null) {
+ map = new TreeMap<>();
+ }
+
+ map.put(key, value);
+ }
+
+ @Override
+ public String toString() {
+ return "Derived [text=" + text + ", map=" + map + ", toString()=" + super.toString() + "]";
+ }
+ }
+
+ /**
+ * Has {@link GsonJsonAnyGetter} method that overrides the super class' method.
+ */
+ private static class AnyGetterOverride extends Derived {
+ private Map<String, Integer> overMap;
+
+ @GsonJsonAnyGetter
+ private Map<String, Integer> getOverride() {
+ return overMap;
+ }
+ }
+
+ /**
+ * Has {@link GsonJsonAnySetter} method that overrides the super class' method.
+ */
+ private static class AnySetterOverride extends Derived {
+ private Map<String, Integer> overMap;
+
+ @GsonJsonAnySetter
+ private void setOverride(String key, int value) {
+ if (overMap == null) {
+ overMap = new TreeMap<>();
+ }
+
+ overMap.put(key, value);
+ }
+ }
+
+ /**
+ * Has nothing to serialize.
+ */
+ protected static class NothingToSerialize {
+ // not serialized
+ protected String unserialized;
+ }
+
+ /**
+ * Only has getters.
+ */
+ protected static class OnlyGetters {
+ public int getId() {
+ return 1010;
+ }
+ }
+
+ /**
+ * Only has setters.
+ */
+ protected static class OnlySetters {
+ public void setId(int id) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Only has {@link GsonJsonAnyGetter}.
+ */
+ private static class OnlyAnyGetter {
+ @GsonJsonAnyGetter
+ public Map<String, Integer> getOverride() {
+ return null;
+ }
+ }
+
+ /**
+ * Only has {@link GsonJsonAnySetter}.
+ */
+ private static class OnlyAnySetter {
+ @GsonJsonAnySetter
+ public void setOverride(String key, int value) {
+ // do nothing
+ }
+ }
+
+ /**
+ * Used to test serialization of non-static nested classes.
+ */
+ protected static class Container {
+ private int id;
+ private Nested nested;
+
+ public Container() {
+ super();
+ }
+
+ public Container(int id, String value) {
+ this.id = id;
+ this.nested = new Nested(value);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Nested getNested() {
+ return nested;
+ }
+
+ @Override
+ public String toString() {
+ return "Container [id=" + id + ", nested=" + nested + "]";
+ }
+
+
+ protected class Nested {
+ private String value;
+
+ public Nested(String val) {
+ value = val;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "Nested [value=" + value + "]";
+ }
+ }
+ }
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/AdapterTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/AdapterTest.java
index fcb0d9ad..04f37164 100644
--- a/gson/src/test/java/org/onap/policy/common/gson/internal/AdapterTest.java
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/AdapterTest.java
@@ -140,7 +140,7 @@ public class AdapterTest {
Method getter = mget("getMyList");
- Adapter aget = new Adapter(gson, getter, true, getter.getReturnType());
+ Adapter aget = new Adapter(gson, getter, getter.getReturnType());
dataAdapter.reset();
JsonElement tree = aget.toJsonTree(listField);
@@ -148,7 +148,7 @@ public class AdapterTest {
assertEquals(DataAdapterFactory.ENCODED_LIST, tree.toString());
Method setter = AdapterTest.class.getDeclaredMethod("setMyList", List.class);
- Adapter aset = new Adapter(gson, setter, true, setter.getGenericParameterTypes()[0]);
+ Adapter aset = new Adapter(gson, setter, setter.getGenericParameterTypes()[0]);
dataAdapter.reset();
@SuppressWarnings("unchecked")
@@ -168,7 +168,7 @@ public class AdapterTest {
// test getter
- adapter = new Adapter(gson, mget(GET_VALUE_NAME), true, String.class);
+ adapter = new Adapter(gson, mget(GET_VALUE_NAME), String.class);
assertEquals(VALUE_NAME, adapter.getPropName());
assertEquals(MY_NAME + ".getValue", adapter.getFullName());
@@ -177,7 +177,7 @@ public class AdapterTest {
// test setter
- adapter = new Adapter(gson, mset("setValue"), false, String.class);
+ adapter = new Adapter(gson, mset("setValue"), String.class);
assertEquals(VALUE_NAME, adapter.getPropName());
assertEquals(MY_NAME + ".setValue", adapter.getFullName());
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/AnyGetterSerializerTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/AnyGetterSerializerTest.java
new file mode 100644
index 00000000..75128420
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/AnyGetterSerializerTest.java
@@ -0,0 +1,134 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonExclusionStrategy;
+import org.onap.policy.common.gson.internal.AnyGetterSerializer;
+import org.onap.policy.common.gson.internal.DataAdapterFactory.Data;
+
+public class AnyGetterSerializerTest {
+
+ private static DataAdapterFactory dataAdapter = new DataAdapterFactory();
+
+ private static Gson gson = new GsonBuilder().registerTypeAdapterFactory(dataAdapter)
+ .setExclusionStrategies(new JacksonExclusionStrategy()).create();
+
+ private Set<String> set;
+ private AnyGetterSerializer ser;
+
+ /**
+ * Set up.
+ *
+ * @throws Exception if an error occurs
+ */
+ @Before
+ public void setUp() throws Exception {
+ set = new HashSet<>(Arrays.asList("id", "value"));
+ ser = new AnyGetterSerializer(gson, set, MapData.class.getDeclaredMethod("getTheMap"));
+ }
+
+ @Test
+ public void testAddToTree_testCopyLiftedItems() throws Exception {
+ JsonObject tree = new JsonObject();
+ tree.addProperty("hello", "world");
+
+ MapData data = new MapData();
+
+ data.map = DataAdapterFactory.makeMap();
+
+ // this should not be copied because it is in the "set"
+ data.map.put("value", Arrays.asList(new Data(1000)));
+
+ dataAdapter.reset();
+ JsonObject tree2 = tree.deepCopy();
+ ser.addToTree(data, tree2);
+
+ assertTrue(dataAdapter.isDataWritten());
+
+ DataAdapterFactory.addToObject(tree);
+
+ assertEquals(tree.toString(), tree2.toString());
+ }
+
+ @Test
+ public void testAddToTree_NullMap() throws Exception {
+ JsonObject tree = new JsonObject();
+ tree.addProperty("hello", "world");
+
+ MapData data = new MapData();
+
+ // leave "map" unset
+
+ JsonObject tree2 = tree.deepCopy();
+ ser.addToTree(data, tree2);
+
+ assertEquals(tree.toString(), tree2.toString());
+ }
+
+ @Test
+ public void testAddToTree_NotAnObject() throws Exception {
+ ser = new AnyGetterSerializer(gson, set, NotAnObject.class.getDeclaredMethod("getNonMap"));
+
+ JsonObject tree = new JsonObject();
+
+ NotAnObject data = new NotAnObject();
+ data.text = "bye bye";
+
+ assertThatThrownBy(() -> ser.addToTree(data, tree)).isInstanceOf(JsonParseException.class)
+ .hasMessage(AnyGetterSerializer.NOT_AN_OBJECT_ERR + NotAnObject.class.getName() + ".getNonMap");
+ }
+
+ public static class MapData {
+ protected int id;
+ protected String value;
+ protected Map<String, List<Data>> map;
+
+ protected Map<String, List<Data>> getTheMap() {
+ return map;
+ }
+ }
+
+ /**
+ * The "lifted" property is not a JsonObject so it should throw an exception.
+ */
+ public static class NotAnObject {
+ protected String text;
+
+ public String getNonMap() {
+ return text;
+ }
+ }
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/AnySetterDeserializerTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/AnySetterDeserializerTest.java
new file mode 100644
index 00000000..b180605e
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/AnySetterDeserializerTest.java
@@ -0,0 +1,94 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonExclusionStrategy;
+import org.onap.policy.common.gson.internal.AnySetterDeserializer;
+import org.onap.policy.common.gson.internal.DataAdapterFactory.Data;
+
+public class AnySetterDeserializerTest {
+
+ private static DataAdapterFactory dataAdapter = new DataAdapterFactory();
+
+ private static Gson gson = new GsonBuilder().registerTypeAdapterFactory(dataAdapter)
+ .setExclusionStrategies(new JacksonExclusionStrategy()).create();
+
+ private Set<String> set;
+ private AnySetterDeserializer deser;
+
+ /**
+ * Set up.
+ *
+ * @throws Exception if an error occurs
+ */
+ @Before
+ public void setUp() throws Exception {
+ set = new HashSet<>(Arrays.asList("id", "value"));
+ deser = new AnySetterDeserializer(gson, set,
+ MapData.class.getDeclaredMethod("setItem", String.class, List.class));
+ }
+
+ @Test
+ public void testAnySetterDeserializer() {
+ JsonObject json = new JsonObject();
+
+ // these should not be copied
+ json.addProperty("id", 10);
+ json.addProperty("value", "the-value");
+
+ // these should be copied
+ DataAdapterFactory.addToObject(json);
+
+ MapData data = new MapData();
+ data.map = new TreeMap<>();
+
+ dataAdapter.reset();
+ deser.getFromTree(json, data);
+
+ assertTrue(dataAdapter.isDataRead());
+ assertNotNull(data.map);
+ assertEquals(DataAdapterFactory.makeMap().toString(), data.map.toString());
+ }
+
+ public static class MapData {
+ protected Map<String, List<Data>> map;
+
+ protected void setItem(String key, List<Data> value) {
+ map.put(key, value);
+ }
+ }
+
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/LifterTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/LifterTest.java
new file mode 100644
index 00000000..55a3b674
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/LifterTest.java
@@ -0,0 +1,55 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Test;
+import org.onap.policy.common.gson.internal.Lifter;
+
+public class LifterTest {
+
+ private static Gson gson = new Gson();
+
+ @Test
+ public void testLifter_testShouldLift() throws Exception {
+ Set<String> set = new HashSet<>(Arrays.asList("abc", "def"));
+ Lifter lifter = new Lifter(gson, set, LifterTest.class.getDeclaredMethod("getValue"), String.class);
+
+ // should not lift these
+ assertFalse(lifter.shouldLift("abc"));
+ assertFalse(lifter.shouldLift("def"));
+
+ // should lift anything else
+ assertTrue(lifter.shouldLift("hello"));
+ assertTrue(lifter.shouldLift("world"));
+ }
+
+ public String getValue() {
+ return "";
+ }
+
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/MethodAdapterTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodAdapterTest.java
new file mode 100644
index 00000000..9f39e3ce
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodAdapterTest.java
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+import org.junit.Test;
+import org.onap.policy.common.gson.internal.MethodAdapter;
+
+public class MethodAdapterTest {
+ private static final Gson gson = new Gson();
+
+ private String saved;
+
+ @Test
+ public void testMethodAdapter_testInvoke() throws Exception {
+ MethodAdapter adapter =
+ new MethodAdapter(gson, MethodAdapterTest.class.getDeclaredMethod("getValue"), String.class);
+ assertEquals("hello", adapter.invoke(this));
+
+ MethodAdapter adapter2 = new MethodAdapter(gson,
+ MethodAdapterTest.class.getDeclaredMethod("setValue", String.class), String.class);
+ adapter2.invoke(this, "world");
+ assertEquals("world", saved);
+
+ assertThatThrownBy(() -> adapter2.invoke(this, 100)).isInstanceOf(JsonParseException.class)
+ .hasMessage(MethodAdapter.INVOKE_ERR + MethodAdapterTest.class.getName() + ".setValue");
+ }
+
+ public String getValue() {
+ return "hello";
+ }
+
+ public void setValue(String val) {
+ saved = val;
+ }
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/MethodDeserializerTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodDeserializerTest.java
new file mode 100644
index 00000000..338644ae
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodDeserializerTest.java
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import java.util.List;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonExclusionStrategy;
+import org.onap.policy.common.gson.internal.DataAdapterFactory.Data;
+import org.onap.policy.common.gson.internal.MethodDeserializer;
+
+public class MethodDeserializerTest {
+ private static final String PROP_NAME = "text";
+ private static final String METHOD_NAME = "setText";
+ private static final String INITIAL_VALUE = "initial value";
+ private static final String NEW_VALUE = "new value";
+
+ private static DataAdapterFactory dataAdapter = new DataAdapterFactory();
+
+ private static Gson gson = new GsonBuilder().registerTypeAdapterFactory(dataAdapter)
+ .setExclusionStrategies(new JacksonExclusionStrategy()).create();
+
+ private MethodDeserializer deser;
+
+ private String text;
+
+ private List<Data> listField;
+
+ @Test
+ public void testGetFromTree() throws Exception {
+ deser = new MethodDeserializer(gson, MethodDeserializerTest.class.getDeclaredMethod(METHOD_NAME, String.class));
+
+ // non-existent value - should not overwrite
+ text = INITIAL_VALUE;
+ JsonObject json = new JsonObject();
+ deser.getFromTree(json, this);
+ assertEquals(INITIAL_VALUE, text);
+
+ // null value - should not overwrite
+ text = INITIAL_VALUE;
+ json.add(PROP_NAME, JsonNull.INSTANCE);
+ deser.getFromTree(json, this);
+ assertEquals(INITIAL_VALUE, text);
+
+ // has a value - should store it
+ text = INITIAL_VALUE;
+ json.addProperty(PROP_NAME, NEW_VALUE);
+ deser.getFromTree(json, this);
+ assertEquals(NEW_VALUE, text);
+
+ /*
+ * check list field
+ */
+ deser = new MethodDeserializer(gson, MethodDeserializerTest.class.getDeclaredMethod("setTheList", List.class));
+
+ json = new JsonObject();
+ json.add("theList", DataAdapterFactory.makeArray());
+
+ dataAdapter.reset();
+ listField = null;
+ deser.getFromTree(json, this);
+
+ assertTrue(dataAdapter.isDataRead());
+ assertNotNull(listField);
+ assertEquals(DataAdapterFactory.makeList().toString(), listField.toString());
+ }
+
+ protected void setText(String text) {
+ this.text = text;
+ }
+
+ protected void setTheList(List<Data> lst) {
+ listField = lst;
+ }
+}
diff --git a/gson/src/test/java/org/onap/policy/common/gson/internal/MethodSerializerTest.java b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodSerializerTest.java
new file mode 100644
index 00000000..586bf54d
--- /dev/null
+++ b/gson/src/test/java/org/onap/policy/common/gson/internal/MethodSerializerTest.java
@@ -0,0 +1,88 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.gson.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.List;
+import org.junit.Test;
+import org.onap.policy.common.gson.JacksonExclusionStrategy;
+import org.onap.policy.common.gson.internal.DataAdapterFactory.Data;
+import org.onap.policy.common.gson.internal.MethodSerializer;
+
+public class MethodSerializerTest {
+ private static final String PROP_NAME = "text";
+ private static final String METHOD_NAME = "getText";
+
+ private static DataAdapterFactory dataAdapter = new DataAdapterFactory();
+
+ private static Gson gson = new GsonBuilder().registerTypeAdapterFactory(dataAdapter)
+ .setExclusionStrategies(new JacksonExclusionStrategy()).create();
+
+ private MethodSerializer ser;
+
+ private String text;
+
+ private List<Data> listField;
+
+ @Test
+ public void testAddToTree() throws Exception {
+ ser = new MethodSerializer(gson, MethodSerializerTest.class.getDeclaredMethod(METHOD_NAME));
+
+ // serialize null value first
+ text = null;
+
+ JsonObject json = new JsonObject();
+ ser.addToTree(this, json);
+ assertTrue(json.get(PROP_NAME).isJsonNull());
+
+ // serialize an actual value
+ text = "hello";
+ ser.addToTree(this, json);
+ assertEquals("hello", json.get(PROP_NAME).getAsString());
+
+ /*
+ * check list field
+ */
+ listField = DataAdapterFactory.makeList();
+
+ ser = new MethodSerializer(gson, MethodSerializerTest.class.getDeclaredMethod("getTheList"));
+
+ dataAdapter.reset();
+ JsonElement tree = ser.toJsonTree(listField);
+
+ assertTrue(dataAdapter.isDataWritten());
+ assertEquals(DataAdapterFactory.ENCODED_LIST, tree.toString());
+ }
+
+ protected String getText() {
+ return text;
+ }
+
+ protected List<Data> getTheList() {
+ return listField;
+ }
+}