aboutsummaryrefslogtreecommitdiffstats
path: root/gson/src/main/java/org
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/src/main/java/org
parent5ddd8900f821d43ab4710309da72cf71cda9c805 (diff)
parent3cc17f964e46578f8ff6275072d1c77dafa551dd (diff)
Merge "Add jackson behavior for methods"
Diffstat (limited to 'gson/src/main/java/org')
-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
8 files changed, 577 insertions, 4 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)));
+ }
+}