2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.drools.protocol.coders;
23 import com.fasterxml.jackson.annotation.JsonIgnore;
24 import com.google.gson.Gson;
25 import com.google.gson.GsonBuilder;
26 import com.google.gson.JsonDeserializationContext;
27 import com.google.gson.JsonDeserializer;
28 import com.google.gson.JsonElement;
29 import com.google.gson.JsonPrimitive;
30 import com.google.gson.JsonSerializationContext;
31 import com.google.gson.JsonSerializer;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.Type;
35 import java.time.Instant;
36 import java.time.ZonedDateTime;
37 import java.time.format.DateTimeFormatter;
38 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
39 import org.onap.policy.drools.controller.DroolsController;
40 import org.onap.policy.drools.controller.DroolsControllerConstants;
41 import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 * Tools used for encoding/decoding using GSON.
48 class GsonProtocolCoderToolset extends ProtocolCoderToolset {
49 private static final String FETCH_CLASS_EX_MSG = "cannot fetch application class ";
54 private static final Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class);
57 * Formatter for JSON encoding/decoding.
61 public static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx");
65 public static final DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT;
68 * Adapter for ZonedDateTime.
70 public static class GsonUtcAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
72 public ZonedDateTime deserialize(JsonElement element, Type type,
73 JsonDeserializationContext context) {
75 return ZonedDateTime.parse(element.getAsString(), format);
76 } catch (final Exception e) {
77 logger.info("GsonUTCAdapter: cannot parse {} because of {}", element, e.getMessage(), e);
83 public JsonElement serialize(ZonedDateTime datetime, Type type,
84 JsonSerializationContext context) {
85 return new JsonPrimitive(datetime.format(format));
89 public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
92 public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
93 return Instant.ofEpochMilli(json.getAsLong());
97 public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
98 return new JsonPrimitive(src.toEpochMilli());
109 protected final Gson decoder = new GsonBuilder().disableHtmlEscaping()
110 .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
111 .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
118 protected final Gson encoder = new GsonBuilder().disableHtmlEscaping()
119 .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
120 .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
123 * Toolset to encode/decode tools associated with a topic.
125 * @param eventProtocolParams parameter object for event encoder
126 * @param controllerId controller id
128 public GsonProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) {
129 super(eventProtocolParams, controllerId);
133 * gets the Gson decoder.
135 * @return the Gson decoder
139 protected Gson getDecoder() {
144 * gets the Gson encoder.
146 * @return the Gson encoder
150 protected Gson getEncoder() {
158 public Object decode(String json) {
160 final DroolsController droolsController =
161 DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, "");
162 if (droolsController == null) {
163 logger.warn("{}: no drools-controller to process {}", this, json);
164 throw new IllegalStateException("no drools-controller to process event");
167 final CoderFilters decoderFilter = this.filter(json);
168 if (decoderFilter == null) {
169 logger.debug("{}: no decoder to process {}", this, json);
170 throw new UnsupportedOperationException("no decoder to process event");
173 Class<?> decoderClass;
175 decoderClass = droolsController.fetchModelClass(decoderFilter.getCodedClass());
176 if (decoderClass == null) {
177 logger.warn("{}: cannot fetch application class {}", this, decoderFilter.getCodedClass());
178 throw new IllegalStateException(
179 FETCH_CLASS_EX_MSG + decoderFilter.getCodedClass());
181 } catch (final Exception e) {
182 logger.warn("{}: cannot fetch application class {} because of {}", this,
183 decoderFilter.getCodedClass(), e.getMessage());
184 throw new UnsupportedOperationException(
185 FETCH_CLASS_EX_MSG + decoderFilter.getCodedClass(), e);
188 if (this.customCoder != null) {
190 final Class<?> gsonClassContainer =
191 droolsController.fetchModelClass(this.customCoder.getClassContainer());
192 final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
193 final Object gsonObject = gsonField.get(null);
194 final Method fromJsonMethod = gsonObject.getClass().getDeclaredMethod("fromJson",
195 new Class[] {String.class, Class.class});
196 return fromJsonMethod.invoke(gsonObject, json, decoderClass);
197 } catch (final Exception e) {
198 logger.warn("{}: cannot fetch application class {} because of {}", this,
199 decoderFilter.getCodedClass(), e.getMessage());
200 throw new UnsupportedOperationException(
201 FETCH_CLASS_EX_MSG + decoderFilter.getCodedClass(), e);
205 return this.decoder.fromJson(json, decoderClass);
206 } catch (final Exception e) {
207 logger.warn("{} cannot decode {} into {} because of {}", this, json, decoderClass.getName(),
209 throw new UnsupportedOperationException(
210 "cannont decode into " + decoderFilter.getCodedClass(), e);
219 public String encode(Object event) {
221 if (this.customCoder != null) {
223 final DroolsController droolsController =
224 DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, null);
225 final Class<?> gsonClassContainer =
226 droolsController.fetchModelClass(this.customCoder.getClassContainer());
227 final Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
228 final Object gsonObject = gsonField.get(null);
229 final Method toJsonMethod =
230 gsonObject.getClass().getDeclaredMethod("toJson", new Class[] {Object.class});
231 return (String) toJsonMethod.invoke(gsonObject, event);
232 } catch (final Exception e) {
233 logger.warn("{} cannot custom-encode {} because of {}", this, event, e.getMessage(), e);
234 throw new UnsupportedOperationException("event cannot be encoded", e);
238 return this.encoder.toJson(event);
239 } catch (final Exception e) {
240 logger.warn("{} cannot encode {} because of {}", this, event, e.getMessage(), e);
241 throw new UnsupportedOperationException("event cannot be encoded", e);
247 public String toString() {
248 final StringBuilder builder = new StringBuilder();
249 builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]");
250 return builder.toString();