2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2022 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.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.JsonDeserializationContext;
26 import com.google.gson.JsonDeserializer;
27 import com.google.gson.JsonElement;
28 import com.google.gson.JsonPrimitive;
29 import com.google.gson.JsonSerializationContext;
30 import com.google.gson.JsonSerializer;
31 import java.lang.reflect.Type;
32 import java.time.Instant;
33 import java.time.ZonedDateTime;
34 import java.time.format.DateTimeFormatter;
35 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
36 import org.onap.policy.drools.controller.DroolsControllerConstants;
37 import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * Tools used for encoding/decoding using GSON.
44 class GsonProtocolCoderToolset extends ProtocolCoderToolset {
45 private static final String CANNOT_FETCH_CLASS = "{}: cannot fetch application class {}";
46 private static final String FETCH_CLASS_EX_MSG = "cannot fetch application class ";
51 private static final Logger logger = LoggerFactory.getLogger(GsonProtocolCoderToolset.class);
54 * Formatter for JSON encoding/decoding.
57 public static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx");
60 * Adapter for ZonedDateTime.
62 public static class GsonUtcAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
64 public ZonedDateTime deserialize(JsonElement element, Type type,
65 JsonDeserializationContext context) {
67 return ZonedDateTime.parse(element.getAsString(), format);
68 } catch (final Exception e) {
69 logger.info("GsonUTCAdapter: cannot parse {} because of {}", element, e.getMessage(), e);
75 public JsonElement serialize(ZonedDateTime datetime, Type type,
76 JsonSerializationContext context) {
77 return new JsonPrimitive(datetime.format(format));
81 public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
84 public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
85 return Instant.ofEpochMilli(json.getAsLong());
89 public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
90 return new JsonPrimitive(src.toEpochMilli());
99 protected final Gson decoder = new GsonBuilder().disableHtmlEscaping()
100 .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
101 .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
107 protected final Gson encoder = new GsonBuilder().disableHtmlEscaping()
108 .registerTypeAdapter(ZonedDateTime.class, new GsonUtcAdapter())
109 .registerTypeAdapter(Instant.class, new GsonInstantAdapter()).create();
112 * Toolset to encode/decode tools associated with a topic.
114 * @param eventProtocolParams parameter object for event encoder
115 * @param controllerId controller id
117 public GsonProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) {
118 super(eventProtocolParams, controllerId);
122 * gets the Gson decoder.
124 * @return the Gson decoder
127 protected Gson getDecoder() {
132 * gets the Gson encoder.
134 * @return the Gson encoder
137 protected Gson getEncoder() {
145 public Object decode(String json) {
147 final var droolsController =
148 DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, "");
149 if (droolsController == null) {
150 logger.warn("{}: no drools-controller to process {}", this, json);
151 throw new IllegalStateException("no drools-controller to process event");
154 final CoderFilters decoderFilter = this.filter(json);
155 if (decoderFilter == null) {
156 logger.debug("{}: no decoder to process {}", this, json);
157 throw new UnsupportedOperationException("no decoder to process event");
160 Class<?> decoderClass;
162 decoderClass = droolsController.fetchModelClass(decoderFilter.getFactClass());
163 if (decoderClass == null) {
164 logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass());
165 throw new IllegalStateException(
166 FETCH_CLASS_EX_MSG + decoderFilter.getFactClass());
168 } catch (final Exception e) {
169 logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass());
170 throw new UnsupportedOperationException(
171 FETCH_CLASS_EX_MSG + decoderFilter.getFactClass(), e);
174 if (this.customCoder != null) {
176 final var gsonClassContainer =
177 droolsController.fetchModelClass(this.customCoder.getClassContainer());
178 final var gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
179 final var gsonObject = gsonField.get(null);
180 final var fromJsonMethod = gsonObject.getClass().getDeclaredMethod("fromJson",
181 String.class, Class.class);
182 return fromJsonMethod.invoke(gsonObject, json, decoderClass);
183 } catch (final Exception e) {
184 logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass());
185 throw new UnsupportedOperationException(
186 FETCH_CLASS_EX_MSG + decoderFilter.getFactClass(), e);
190 return this.decoder.fromJson(json, decoderClass);
191 } catch (final Exception e) {
192 logger.warn("{} cannot decode {} into {}", this, json, decoderClass.getName());
193 throw new UnsupportedOperationException(
194 "cannot decode into " + decoderFilter.getFactClass(), e);
203 public String encode(Object event) {
205 if (this.customCoder != null) {
207 final var droolsController =
208 DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, null);
209 final Class<?> gsonClassContainer =
210 droolsController.fetchModelClass(this.customCoder.getClassContainer());
211 final var gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField);
212 final var gsonObject = gsonField.get(null);
213 final var toJsonMethod =
214 gsonObject.getClass().getDeclaredMethod("toJson", Object.class);
215 return (String) toJsonMethod.invoke(gsonObject, event);
216 } catch (final Exception e) {
217 logger.warn("{} cannot custom-encode {}", this, event);
218 throw new UnsupportedOperationException("event cannot be encoded", e);
222 return this.encoder.toJson(event);
223 } catch (final Exception e) {
224 logger.warn("{} cannot encode {}", this, event);
225 throw new UnsupportedOperationException("event cannot be encoded", e);
231 public String toString() {
232 return "GsonProtocolCoderToolset [toString()=" + super.toString() + "]";