2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright 2018 TechMahindra
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=========================================================
20 package org.onap.universalvesadapter.utils;
22 import java.io.IOException;
24 import java.util.TreeSet;
26 import org.onap.universalvesadapter.exception.MapperConfigException;
27 import org.onap.universalvesadapter.mappingconfig.Entry;
28 import org.onap.universalvesadapter.mappingconfig.Evaluation;
29 import org.onap.universalvesadapter.mappingconfig.MapperConfig;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.fasterxml.jackson.databind.JsonNode;
34 import com.fasterxml.jackson.databind.ObjectMapper;
37 * This class will be used in Future for different telemetry data:
38 * This class will be utility class to read the mapper config file and parse the
39 * config to prepare the grammar to detect the incoming json's event type.
44 public class MapperConfigUtils {
46 private static final Logger LOGGER = LoggerFactory.getLogger(MapperConfigUtils.class);
47 private static Set<Entry> entries = new TreeSet<>((o1, o2) -> o1.getPriority().compareTo(o2.getPriority()));
49 private enum JoinOperator {
52 private final String value;
54 private JoinOperator(final String value) {
58 public String getValue() {
63 private enum ExpressionOperator {
64 EQUALS("EQUALS"), STARTSWITH("STARTSWITH"), ENDSWITH("ENDSWITH"), CONTAINS("CONTAINS");
66 private final String value;
68 private ExpressionOperator(final String value) {
72 public String getValue() {
77 private enum DataType {
78 STRING("STRING"), DOUBLE("DOUBLE");
80 private final String value;
82 private DataType(final String value) {
86 public String getValue() {
97 public static void main(String[] args) {
99 String mappingFile = " { " + " \"entries\": [{ " + " \"priority\": 4, " + " \"evaluation\": { "
100 + " \"operand\": \"AND\", " + " \"field\": null, " + " \"value\": null, "
101 + " \"datatype\": null, " + " \"lhs\": { " + " \"operand\": \"OR\", "
102 + " \"field\": null, " + " \"value\": null, "
103 + " \"datatype\": null, " + " \"lhs\": { "
104 + " \"operand\": \"EQUALS\", " + " \"field\": \"domain\", "
105 + " \"value\": \"snmp-heartbeat\", " + " \"datatype\": \"string\", "
106 + " \"lhs\": null, " + " \"rhs\": null " + " }, "
107 + " \"rhs\": { " + " \"operand\": \"EQUALS\", "
108 + " \"field\": \"domain\", " + " \"value\": \"snmp-fault\", "
109 + " \"datatype\": \"string\", " + " \"lhs\": null, "
110 + " \"rhs\": null " + " } " + " }, " + " \"rhs\": { "
111 + " \"operand\": \"EQUALS\", " + " \"field\": \"trap version\", "
112 + " \"value\": \"1.2\", " + " \"datatype\": \"float\", "
113 + " \"lhs\": null, " + " \"rhs\": null " + " } " + " }, "
114 + " \"result\": \"smooks.config\" " + " }, { " + " \"priority\": 1, "
115 + " \"evaluation\": { " + " \"operand\": \"AND\", " + " \"field\": null, "
116 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
117 + " \"operand\": \"OR\", " + " \"field\": null, "
118 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
119 + " \"operand\": \"EQUALS\", " + " \"field\": \"domain\", "
120 + " \"value\": \"snmp-heartbeat\", " + " \"datatype\": \"string\", "
121 + " \"lhs\": null, " + " \"rhs\": null " + " }, "
122 + " \"rhs\": { " + " \"operand\": \"EQUALS\", "
123 + " \"field\": \"domain\", " + " \"value\": \"snmp-fault\", "
124 + " \"datatype\": \"string\", " + " \"lhs\": null, "
125 + " \"rhs\": null " + " } " + " }, " + " \"rhs\": { "
126 + " \"operand\": \"EQUALS\", " + " \"field\": \"trap version\", "
127 + " \"value\": \"1.2\", " + " \"datatype\": \"float\", "
128 + " \"lhs\": null, " + " \"rhs\": null " + " } " + " }, "
129 + " \"result\": \"smooks.config\" " + " }, { " + " \"priority\": 3, "
130 + " \"evaluation\": { " + " \"operand\": \"AND\", " + " \"field\": null, "
131 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
132 + " \"operand\": \"OR\", " + " \"field\": null, "
133 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
134 + " \"operand\": \"EQUALS\", " + " \"field\": \"domain\", "
135 + " \"value\": \"snmp-heartbeat\", " + " \"datatype\": \"string\", "
136 + " \"lhs\": null, " + " \"rhs\": null " + " }, "
137 + " \"rhs\": { " + " \"operand\": \"EQUALS\", "
138 + " \"field\": \"domain\", " + " \"value\": \"snmp-fault\", "
139 + " \"datatype\": \"string\", " + " \"lhs\": null, "
140 + " \"rhs\": null " + " } " + " }, " + " \"rhs\": { "
141 + " \"operand\": \"EQUALS\", " + " \"field\": \"trap version\", "
142 + " \"value\": \"1.2\", " + " \"datatype\": \"float\", "
143 + " \"lhs\": null, " + " \"rhs\": null " + " } " + " }, "
144 + " \"result\": \"smooks.config\" " + " }, { " + " \"priority\": 2, "
145 + " \"evaluation\": { " + " \"operand\": \"AND\", " + " \"field\": null, "
146 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
147 + " \"operand\": \"OR\", " + " \"field\": null, "
148 + " \"value\": null, " + " \"datatype\": null, " + " \"lhs\": { "
149 + " \"operand\": \"EQUALS\", " + " \"field\": \"domain\", "
150 + " \"value\": \"snmp-heartbeat\", " + " \"datatype\": \"string\", "
151 + " \"lhs\": null, " + " \"rhs\": null " + " }, "
152 + " \"rhs\": { " + " \"operand\": \"EQUALS\", "
153 + " \"field\": \"domain\", " + " \"value\": \"snmp-fault\", "
154 + " \"datatype\": \"string\", " + " \"lhs\": null, "
155 + " \"rhs\": null " + " } " + " }, " + " \"rhs\": { "
156 + " \"operand\": \"EQUALS\", " + " \"field\": \"trap version\", "
157 + " \"value\": \"1.2\", " + " \"datatype\": \"float\", "
158 + " \"lhs\": null, " + " \"rhs\": null " + " } " + " }, "
159 + " \"result\": \"smooks.config\" " + " }] " + "}";
160 String incomingJsonString = "{\"domain\":\"snmp-heartbeat\",\"trap version\":1.2}";
163 readMapperConfigFile(mappingFile);
164 checkIncomingJsonForMatchingDomain(incomingJsonString);
165 } catch (MapperConfigException e) {
166 LOGGER.error("Exception in mapperConfigFile reading:{}",e);
172 * Checks incoming json to see which of the domain it mathces as per mapper
173 * config entries. If nothing matches, a default mapping will be used.
175 * @param incomingJsonString
177 * @throws MapperConfigException
178 * if error occurs in operation
180 public static String checkIncomingJsonForMatchingDomain(String incomingJsonString) throws MapperConfigException {
181 ObjectMapper mapper = new ObjectMapper();
182 JsonNode actualObj = null;
184 actualObj = mapper.readTree(incomingJsonString);
185 } catch (IOException exception) {
186 throw new MapperConfigException("Unable to read incoming json in a tree " + exception.getMessage(),
189 for (Entry entry : entries) {
191 boolean result = false;
192 result = evaluateEntryMatch(entry.getEvaluation(), actualObj);
194 return entry.getResult();
201 * Reads the mapper config file.
203 * @param mappingFileData
204 * string json for mapper config
205 * @throws MapperConfigException
206 * if error in mapper config
208 public static void readMapperConfigFile(String mappingFileData) throws MapperConfigException {
210 ObjectMapper name = new ObjectMapper();
211 MapperConfig config = null;
213 config = name.readValue(mappingFileData, MapperConfig.class);
214 } catch (IOException exception) {
215 throw new MapperConfigException("Unable to read config file for reason...\n " + exception.getMessage(),
218 LOGGER.debug("Read config file content into :{}",config);
220 if (null != config) {
221 entries.addAll(config.getEntries());
223 throw new MapperConfigException("Unable to generate configuration for different domains.");
228 * Evaluates the passed in {@code Evaluation} instance and return boolean
232 * evaluation instance
234 * Json node with values to compare with
235 * @return true if matches evaluation else false
236 * @throws MapperConfigException
237 * error in evaluation
239 public static boolean evaluateEntryMatch(Evaluation evaluation, JsonNode actualObj) throws MapperConfigException {
240 if (null == evaluation) {
241 throw new MapperConfigException("Cannot have null evaluation");
243 if (null != evaluation.getOperand()) {
245 if (MapperConfigUtils.isValidEnum(JoinOperator.class, evaluation.getOperand())) {
246 // if(JOIN_OPERATOR.contains(evaluation.getOperand())){
247 switch (JoinOperator.valueOf(evaluation.getOperand())) {
249 return evaluateEntryMatch(evaluation.getLhs(), actualObj)
250 && evaluateEntryMatch(evaluation.getRhs(), actualObj);
252 return evaluateEntryMatch(evaluation.getLhs(), actualObj)
253 || evaluateEntryMatch(evaluation.getRhs(), actualObj);
259 if (MapperConfigUtils.isValidEnum(ExpressionOperator.class, evaluation.getOperand())) {
260 // if(EXPR_OPERATOR.contains(evaluation.getOperand())){
262 // currently it is assumed field being compared is first level
263 // child of incoming JSON structure.
264 // If needed, can write a JsonPath implementation later
265 String field = evaluation.getField();
266 if (null != field && null != evaluation.getDatatype() && actualObj.has(field)) {
267 switch (ExpressionOperator.valueOf(evaluation.getOperand())) {
269 if (MapperConfigUtils.isValidEnum(DataType.class, evaluation.getDatatype())) {
270 switch (DataType.valueOf(evaluation.getDatatype())) {
272 if (null != actualObj.get(field))
273 return actualObj.get(field).asText().equals(evaluation.getValue());
276 if (null != actualObj.get(field))
277 return actualObj.get(field).asDouble() == Double
278 .valueOf(evaluation.getValue());
287 if (MapperConfigUtils.isValidEnum(DataType.class, evaluation.getDatatype())) {
288 switch (DataType.valueOf(evaluation.getDatatype())) {
290 if (null != actualObj.get(field))
291 return actualObj.get(field).asText().startsWith(evaluation.getValue());
300 if (MapperConfigUtils.isValidEnum(DataType.class, evaluation.getDatatype())) {
301 switch (DataType.valueOf(evaluation.getDatatype())) {
303 if (null != actualObj.get(field))
304 return actualObj.get(field).asText().endsWith(evaluation.getValue());
313 if (MapperConfigUtils.isValidEnum(DataType.class, evaluation.getDatatype())) {
314 switch (DataType.valueOf(evaluation.getDatatype())) {
316 if (null != actualObj.get(field))
317 return actualObj.get(field).asText().contains(evaluation.getValue());
331 throw new MapperConfigException("Not an expected operand as per config for " + evaluation.getField());
336 * <p>Checks if the specified name is a valid enum for the class.</p>
338 * <p>This method differs from {@link Enum#valueOf} in that checks if the name is
339 * a valid enum without needing to catch the exception.</p>
341 * @param <E> the type of the enumeration
342 * @param enumClass the class of the enum to query, not null
343 * @param enumName the enum name, null returns false
344 * @return true if the enum name is valid, otherwise false
347 public static <E extends Enum<E>> boolean isValidEnum(final Class<E> enumClass, final String enumName) {
348 if (enumName == null) {
352 Enum.valueOf(enumClass, enumName);
354 } catch (final IllegalArgumentException ex) {