Fix serialization of update notification payload
[aai/champ.git] / champ-lib / champ-core / src / main / java / org / onap / aai / champcore / event / envelope / util / GsonUtil.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
4  * ===================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017 Amdocs
7  * ===================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22 package org.onap.aai.champcore.event.envelope.util;
23
24 import java.io.IOException;
25 import java.lang.reflect.ParameterizedType;
26 import java.lang.reflect.Type;
27 import java.util.Optional;
28 import com.google.gson.Gson;
29 import com.google.gson.GsonBuilder;
30 import com.google.gson.TypeAdapter;
31 import com.google.gson.TypeAdapterFactory;
32 import com.google.gson.reflect.TypeToken;
33 import com.google.gson.stream.JsonReader;
34 import com.google.gson.stream.JsonToken;
35 import com.google.gson.stream.JsonWriter;
36
37 public class GsonUtil {
38
39     /**
40      * All methods are static.
41      */
42     private GsonUtil() {
43         // Do not instantiate
44     }
45
46     /**
47      * Tell Gson how to handle Optional fields. This factory builds a Type Adapter for a class wrapped
48      * with Optional
49      *
50      */
51     public static class OptionalTypeAdapterFactory implements TypeAdapterFactory {
52         @SuppressWarnings({"unchecked", "rawtypes"})
53         @Override
54         public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
55             Class<T> rawType = (Class<T>) type.getRawType();
56             if (rawType != Optional.class) {
57                 return null;
58             }
59             final ParameterizedType parameterizedType = (ParameterizedType) type.getType();
60             final Type actualType = parameterizedType.getActualTypeArguments()[0];
61             return new OptionalTypeAdapter(gson.getAdapter(TypeToken.get(actualType)));
62         }
63     }
64
65     /**
66      * Implementation of the Optional Type Adapter
67      *
68      * @param <E>
69      */
70     public static class OptionalTypeAdapter<E> extends TypeAdapter<Optional<E>> {
71
72         private final TypeAdapter<E> adapter;
73
74         public static final TypeAdapterFactory FACTORY = new OptionalTypeAdapterFactory();
75
76         /**
77          * @param adapter
78          */
79         public OptionalTypeAdapter(TypeAdapter<E> adapter) {
80             this.adapter = adapter;
81         }
82
83         @Override
84         public void write(JsonWriter out, Optional<E> value) throws IOException {
85             if (value != null && value.isPresent()) { // NOSONAR
86                 adapter.write(out, value.get());
87             } else {
88                 boolean nullsAllowed = out.getSerializeNulls();
89                 if (nullsAllowed) {
90                     out.setSerializeNulls(false);
91                 }
92                 out.nullValue();
93                 if (nullsAllowed) {
94                     out.setSerializeNulls(true);
95                 }
96             }
97         }
98
99         @Override
100         public Optional<E> read(JsonReader in) throws IOException {
101             final JsonToken peek = in.peek();
102             if (peek != JsonToken.NULL) {
103                 return Optional.ofNullable(adapter.read(in));
104             }
105             return Optional.empty();
106         }
107
108     }
109
110     /**
111      * @return a new GsonBuilder with standard settings
112      */
113     public static GsonBuilder createGsonBuilder() {
114         return new GsonBuilder().disableHtmlEscaping().setPrettyPrinting()
115                 .registerTypeAdapterFactory(OptionalTypeAdapter.FACTORY);
116     }
117
118     /**
119      * @return a new Gson instance
120      */
121     public static Gson createGson() {
122         return createGsonBuilder().create();
123     }
124 }