7cf3a2f39af421aab1bb15e7df5d3de3c07ab864
[policy/drools-pdp.git] / policy-management / src / main / java / org / onap / policy / drools / protocol / coders / ProtocolCoderToolset.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd.
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  */
21
22 package org.onap.policy.drools.protocol.coders;
23
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.CopyOnWriteArrayList;
27 import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
28 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * Protocol Coding/Decoding Toolset.
34  */
35 public abstract class ProtocolCoderToolset {
36
37     /**
38      * Logger.
39      */
40     private static Logger logger = LoggerFactory.getLogger(ProtocolCoderToolset.class);
41
42     /**
43      * topic.
44      */
45     protected final String topic;
46
47     /**
48      * controller id.
49      */
50     protected final String controllerId;
51
52     /**
53      * group id.
54      */
55     protected final String groupId;
56
57     /**
58      * artifact id.
59      */
60     protected final String artifactId;
61
62     /**
63      * Protocols and associated Filters.
64      */
65     protected final List<CoderFilters> coders = new CopyOnWriteArrayList<>();
66
67     /**
68      * custom coder.
69      */
70     protected CustomCoder customCoder;
71
72     /**
73      * Constructor.
74      *
75      * @param eventProtocolParams parameter object for event encoder
76      * @param controllerId the controller id
77      * @throws IllegalArgumentException if invalid data has been passed in
78      */
79     protected ProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) {
80
81         if (eventProtocolParams == null || controllerId == null) {
82             throw new IllegalArgumentException("Invalid input");
83         }
84
85         this.topic = eventProtocolParams.getTopic();
86         this.controllerId = controllerId;
87         this.groupId = eventProtocolParams.getGroupId();
88         this.artifactId = eventProtocolParams.getArtifactId();
89         this.coders.add(new CoderFilters(
90                 eventProtocolParams.getEventClass(),
91                 eventProtocolParams.getProtocolFilter(),
92                 eventProtocolParams.getModelClassLoaderHash()));
93         this.customCoder = eventProtocolParams.getCustomCoder();
94     }
95
96     /**
97      * gets the coder + filters associated with this class name.
98      *
99      * @param classname class name
100      * @return the decoder filters or null if not found
101      */
102     public CoderFilters getCoder(String classname) {
103         if (classname == null || classname.isEmpty()) {
104             throw new IllegalArgumentException("no classname provided");
105         }
106
107         for (final CoderFilters decoder : this.coders) {
108             if (decoder.factClass.equals(classname)) {
109                 return decoder;
110             }
111         }
112         return null;
113     }
114
115     /**
116      * get a copy of the coder filters in use.
117      *
118      * @return coder filters
119      */
120     public List<CoderFilters> getCoders() {
121         return new ArrayList<>(this.coders);
122     }
123
124     /**
125      * add coder or replace it exists.
126      *
127      * @param eventClass decoder
128      * @param filter filter
129      */
130     public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) {
131         if (eventClass == null || eventClass.isEmpty()) {
132             throw new IllegalArgumentException("no event class provided");
133         }
134
135         for (final CoderFilters coder : this.coders) {
136             if (coder.getCodedClass().equals(eventClass)) {
137                 coder.setFilter(filter);
138                 coder.setFromClassLoaderHash(modelClassLoaderHash);
139                 return;
140             }
141         }
142         this.coders.add(new CoderFilters(eventClass, filter, modelClassLoaderHash));
143     }
144
145     /**
146      * remove coder.
147      *
148      * @param eventClass event class
149      */
150     public void removeCoders(String eventClass) {
151         if (eventClass == null || eventClass.isEmpty()) {
152             throw new IllegalArgumentException("no event class provided");
153         }
154
155         List<CoderFilters> temp = new ArrayList<>();
156         for (final CoderFilters coder : this.coders) {
157             if (coder.factClass.equals(eventClass)) {
158                 temp.add(coder);
159             }
160         }
161
162         this.coders.removeAll(temp);
163     }
164
165     /**
166      * gets the topic.
167      *
168      * @return the topic
169      */
170     public String getTopic() {
171         return this.topic;
172     }
173
174     /**
175      * gets the controller id.
176      *
177      * @return the controller id
178      */
179     public String getControllerId() {
180         return this.controllerId;
181     }
182
183     /**
184      * Get group id.
185      *
186      * @return the groupId
187      */
188     public String getGroupId() {
189         return this.groupId;
190     }
191
192     /**
193      * Get artifact id.
194      *
195      * @return the artifactId
196      */
197     public String getArtifactId() {
198         return this.artifactId;
199     }
200
201     /**
202      * Get custom coder.
203      *
204      * @return the customCoder
205      */
206     public CustomCoder getCustomCoder() {
207         return this.customCoder;
208     }
209
210     /**
211      * Set custom coder.
212      *
213      * @param customCoder the customCoder to set.
214      */
215     public void setCustomCoder(CustomCoder customCoder) {
216         this.customCoder = customCoder;
217     }
218
219     /**
220      * performs filtering on a json string.
221      *
222      * @param json json string
223      * @return the decoder that passes the filter, otherwise null
224      * @throws UnsupportedOperationException can't filter
225      * @throws IllegalArgumentException invalid input
226      */
227     protected CoderFilters filter(String json) {
228
229
230         // 1. Get list of decoding classes for this controller Id and topic
231         // 2. If there are no classes, return error
232         // 3. Otherwise, from the available classes for decoding, pick the first one that
233         // passes the filters
234
235         // Don't parse if it is not necessary
236
237         if (this.coders.isEmpty()) {
238             throw new IllegalStateException("No coders available");
239         }
240
241         for (final CoderFilters decoder : this.coders) {
242             try {
243                 boolean accepted = decoder.getFilter().accept(json);
244                 if (accepted) {
245                     return decoder;
246                 }
247             } catch (final Exception e) {
248                 logger.info("{}: unexpected failure accepting {} because of {}", this, json,
249                         e.getMessage(), e);
250                 // continue
251             }
252         }
253
254         return null;
255     }
256
257     /**
258      * Decode json into a POJO object.
259      *
260      * @param json json string
261      *
262      * @return a POJO object for the json string
263      * @throws IllegalArgumentException if an invalid parameter has been received
264      * @throws UnsupportedOperationException if parsing into POJO is not possible
265      */
266     public abstract Object decode(String json);
267
268     /**
269      * Encodes a POJO object into a JSON String.
270      *
271      * @param event JSON POJO event to be converted to String
272      * @return JSON string version of POJO object
273      * @throws IllegalArgumentException if an invalid parameter has been received
274      * @throws UnsupportedOperationException if parsing into POJO is not possible
275      */
276     public abstract String encode(Object event);
277
278     @Override
279     public String toString() {
280         final StringBuilder builder = new StringBuilder();
281         builder.append("ProtocolCoderToolset [topic=").append(this.topic).append(", controllerId=")
282         .append(this.controllerId).append(", groupId=").append(this.groupId).append(", artifactId=")
283         .append(this.artifactId).append(", coders=").append(this.coders)
284         .append(", customCoder=").append(this.customCoder).append("]");
285         return builder.toString();
286     }
287 }