diff options
author | Jorge Hernandez <jorge.hernandez-herrero@att.com> | 2019-02-22 13:25:42 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2019-02-22 13:25:42 +0000 |
commit | c150cf1a2327696e289c3a80ef28842f014b1866 (patch) | |
tree | 7cfa7224433a6841573e7942efdf199d007adebc | |
parent | d914823eb7a992cd3410072970a2643c7d0c432c (diff) | |
parent | fa2a5a43c82cd35cca9e7d4b51f83ce70e1e3e59 (diff) |
Merge "Add Nested JSON Filtering"
8 files changed, 355 insertions, 829 deletions
diff --git a/policy-management/pom.xml b/policy-management/pom.xml index 81edf7a0..d48d3ffb 100644 --- a/policy-management/pom.xml +++ b/policy-management/pom.xml @@ -241,6 +241,11 @@ <artifactId>gson-javatime-serialisers</artifactId> <version>1.1.1</version> </dependency> + + <dependency> + <groupId>com.jayway.jsonpath</groupId> + <artifactId>json-path</artifactId> + </dependency> <dependency> <groupId>org.apache.commons</groupId> diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java index 24fc6de9..16daa947 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Properties; - import org.onap.policy.common.endpoints.event.comm.Topic; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -38,7 +37,6 @@ import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; -import org.onap.policy.drools.utils.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,11 +48,11 @@ public interface DroolsControllerFactory { /** * Constructs a Drools Controller based on properties. - * + * * @param properties properties containing initialization parameters * @param eventSources list of event sources * @param eventSinks list of event sinks - * + * * @return the instantiated Drools Controller * @throws IllegalArgumentException with invalid parameters * @throws LinkageError Failure to link rules and models in Drools Libraries @@ -64,13 +62,13 @@ public interface DroolsControllerFactory { /** * Explicit construction of a Drools Controller. - * + * * @param groupId maven group id of drools artifact * @param artifactId maven artifact id of drools artifact * @param version maven version id of drools artifact * @param decoderConfigurations list of decoder configurations * @param encoderConfigurations list of encoder configurations - * + * * @return the instantiated Drools Controller * @throws IllegalArgumentException with invalid parameters * @throws LinkageError Failure to link rules and models in Drools Libraries @@ -81,7 +79,7 @@ public interface DroolsControllerFactory { /** * Releases the Drools Controller from operation. - * + * * @param controller the Drools Controller to shut down */ public void shutdown(DroolsController controller); @@ -93,7 +91,7 @@ public interface DroolsControllerFactory { /** * Destroys and releases resources for a Drools Controller. - * + * * @param controller the Drools Controller to destroy */ public void destroy(DroolsController controller); @@ -105,11 +103,11 @@ public interface DroolsControllerFactory { /** * Gets the Drools Controller associated with the maven group and artifact id. - * + * * @param groupId maven group id of drools artifact * @param artifactId maven artifact id of drools artifact * @param version maven version id of drools artifact - * + * * @return the Drools Controller * @throws IllegalArgumentException with invalid parameters */ @@ -117,7 +115,7 @@ public interface DroolsControllerFactory { /** * returns the current inventory of Drools Controllers. - * + * * @return a list of Drools Controllers */ public List<DroolsController> inventory(); @@ -208,7 +206,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /* * The Null Drools Controller for no maven coordinates is always here so when no * coordinates present, this is the return point - * + * * assert (controllerCopy instanceof NullDroolsController) */ if (droolsControllers.containsKey(controllerId)) { @@ -245,7 +243,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /** * find out decoder classes and filters. - * + * * @param properties properties with information about decoders * @param topicEntities topic sources * @return list of topics, each with associated decoder classes, each with a list of associated @@ -313,7 +311,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { // 3. second the list of classes associated with each topic String eventClasses = properties - .getProperty(propertyTopicEntityPrefix + firstTopic + .getProperty(propertyTopicEntityPrefix + firstTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX); if (eventClasses == null || eventClasses.isEmpty()) { @@ -328,54 +326,14 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { for (String theClass : topicClasses) { - // 4. third, for each coder class, get the list of field filters + // 4. third, for each coder class, get the filter expression String filter = properties - .getProperty(propertyTopicEntityPrefix + firstTopic + .getProperty(propertyTopicEntityPrefix + firstTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX + "." + theClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX); - List<Pair<String, String>> filters = new ArrayList<>(); - - if (filter == null || filter.isEmpty()) { - // 4. topic -> class -> with no filters - - JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); - PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter); - classes2Filters.add(class2Filters); - continue; - } - - // There are filters associated with the applicability of - // this class for decoding. - List<String> listOfFilters = new ArrayList<>(Arrays.asList(filter.split("\\s*,\\s*"))); - - for (String nameValue : listOfFilters) { - String fieldName; - String regexValue; - - String[] nameValueSplit = nameValue.split("\\s*=\\s*"); - if (nameValueSplit.length <= 0 || nameValueSplit.length > 2) { - // TODO warn - // skip - continue; - } - - if (nameValueSplit.length == 2) { - fieldName = nameValueSplit[0]; - regexValue = nameValueSplit[1]; - } else if (nameValueSplit.length == 1) { - fieldName = nameValueSplit[0]; - regexValue = null; - } else { - // unreachable - continue; - } - - filters.add(new Pair<String, String>(fieldName, regexValue)); - } - - JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); + JsonProtocolFilter protocolFilter = new JsonProtocolFilter(filter); PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter); classes2Filters.add(class2Filters); } @@ -408,7 +366,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /** * unmanage the drools controller. - * + * * @param controller the controller */ protected void unmanage(DroolsController controller) { diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java index f65efaed..2ccc010f 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,378 +20,120 @@ package org.onap.policy.drools.protocol.coders; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.Option; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import org.onap.policy.drools.utils.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * JSON Protocol Filter. - */ +/** JSON Protocol Filter. */ public class JsonProtocolFilter { - private static final String MISSING_RULE_NAME = "no rule name provided"; - /** - * Logger. - */ - private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class); - - /** - * Helper class to collect Filter information. - */ - public static class FilterRule { - /** - * Field name. - */ - private String name; - - /** - * Field Value regex. - */ - private String regex; - - /** - * Filter Constructor. - * - * @param name field name - * @param regex field regex value - */ - public FilterRule(String name, String regex) { - this.setName(name); - this.setRegex(regex); - } - - /** - * Default constructor (for serialization only). - */ - public FilterRule() { - super(); - } - - /** - * gets name. - * - * @return name - */ - public String getName() { - return name; - } - - /** - * gets regex. - * - * @return regular expression string - */ - public String getRegex() { - return regex; - } - - /** - * Sets field name. - * - * @param name field name - */ - public void setName(String name) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("filter field name must be provided"); - } - - this.name = name; - } - - /** - * sets regex name. - * - * @param regex expression - */ - public void setRegex(String regex) { - if (regex == null || regex.isEmpty()) { - this.regex = ".*"; - } - - this.regex = regex; - } + /** Default filter to match anything. */ + public static final String MATCH_ANY = "[?($ =~ /.*/)]"; - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]"); - return builder.toString(); - } - } + /** Logger. */ + private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class); - /** - * all the filters to be applied. - */ - protected List<FilterRule> rules = new CopyOnWriteArrayList<>(); + /** A rule based on a JsonPath expression that is used for filtering. */ + private String rule; /** - * Create a Protocol Filter. - * - * @throws IllegalArgumentException an invalid input has been provided + * Default constructor (for serialization only). */ public JsonProtocolFilter() { super(); + this.setRule(null); } /** * Constructor. - * - * @param filters filter list - * - * @throws IllegalArgumentException an invalid input has been provided - */ - public JsonProtocolFilter(List<FilterRule> filters) { - List<FilterRule> temp = new ArrayList<>(); - for (FilterRule rule : filters) { - if (rule.getName() == null || rule.getName().isEmpty()) { - continue; - } - - if (rule.getRegex() == null || rule.getRegex().isEmpty()) { - rule.setRegex(".*"); - } - - temp.add(rule); - } - - this.rules.addAll(temp); - } - - /** - * From raw filters. - * - * @param rawFilters raw filter initialization - * + * + * @param rule the JsonPath expression used for the filter rule * @throws IllegalArgumentException an invalid input has been provided */ - public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) { - - if (rawFilters == null) { - throw new IllegalArgumentException("No raw filters provided"); - } - - List<FilterRule> filters = new ArrayList<>(); - for (Pair<String, String> filterPair: rawFilters) { - if (filterPair.first() == null || filterPair.first().isEmpty()) { - continue; - } - - filters.add(new FilterRule(filterPair.first(), filterPair.second())); - } - return new JsonProtocolFilter(filters); + public JsonProtocolFilter(String rule) { + this.setRule(rule); } /** - * are there any filters. - * - * @return true if there are filters, false otherwise + * Gets the filter expression rule. + * + * @return the filter expression associated with this JsonProtocolFilter */ - public boolean isRules() { - return !this.rules.isEmpty(); + public String getRule() { + return this.rule; } /** - * accept a JSON string as conformant it if passes all filters. - * - * @param json json is a JSON object - * @return true if json string is conformant - * - * @throws IllegalArgumentException an invalid input has been provided + * Sets the filter expression rule. + * + * @param rule the JsonPath expression rule */ - public boolean accept(JsonElement json) { - if (json == null) { - throw new IllegalArgumentException("no JSON provided"); - } - - if (!json.isJsonObject()) { - return false; - } - - if (rules.isEmpty()) { - return true; - } - - try { - JsonObject event = json.getAsJsonObject(); - for (FilterRule filter: rules) { - if (filter.getRegex() == null - || filter.getRegex().isEmpty() - || ".*".equals(filter.getRegex())) { - - // Only check for presence - if (!event.has(filter.getName())) { - return false; - } - } else { - JsonElement field = event.get(filter.getName()); - if (field == null) { - return false; - } - - String fieldValue = field.getAsString(); - if (!fieldValue.matches(filter.getRegex())) { - return false; - } - } - } - return true; - } catch (Exception e) { - throw new IllegalArgumentException(e); + public void setRule(String rule) { + String ruleExpression = rule; + if (rule == null || rule.isEmpty()) { + ruleExpression = MATCH_ANY; } + this.rule = ruleExpression; } /** - * Accept a JSON string as conformant it if passes all filters. - * - * @param json json string - * @return true if json string is conformant - * - * @throws IllegalArgumentException an invalid input has been provided + * Accepts a JSON message if there is a match on the filter expression. + * + * @return true if a match is found or the rule uses the match any policy, false otherwise */ public boolean accept(String json) { - if (json == null || json.isEmpty()) { - throw new IllegalArgumentException("no JSON provided"); - } - - if (rules.isEmpty()) { + if (MATCH_ANY.equals(this.rule)) { return true; } - - try { - JsonElement element = new JsonParser().parse(json); - if (element == null || !element.isJsonObject()) { - return false; - } - - return this.accept(element.getAsJsonObject()); - } catch (IllegalArgumentException ile) { - throw ile; - } catch (Exception e) { - logger.info("{}: cannot accept {} because of {}", - this, json, e.getMessage(), e); - throw new IllegalArgumentException(e); - } - } - - public List<FilterRule> getRules() { - return new ArrayList<>(this.rules); + return !filter(json).isEmpty(); } /** - * Get rules. - * - * @param name name - * @return list of filter rules + * Finds a field based on a path or a subset of the JSON if using an expression. + * + * @param json the JSON string to be parsed + * @return a list of strings that match the expression */ - public List<FilterRule> getRules(String name) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException(MISSING_RULE_NAME); - } - - ArrayList<FilterRule> temp = new ArrayList<>(); - for (FilterRule rule : this.rules) { - if (rule.getName().equals(name)) { - temp.add(rule); - } - } - return temp; + public List<String> filter(String json) { + return filter(json, this.rule); } /** - * Set Rules. - * - * @param rulesFilters filters + * Finds all occurrences of a field in a JSON document based on the JsonPath + * expression. + * + * @param json the JSON string to be parsed + * @param expression the JsonPath expression + * @return a list of matches from the JSON document */ - public void setRules(List<FilterRule> rulesFilters) { - if (rulesFilters == null) { - throw new IllegalArgumentException("no rules provided"); - } - - this.rules.clear(); - this.rules.addAll(rulesFilters); - } - - /** - * Delete rules. - * - * @param name name - */ - public void deleteRules(String name) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException(MISSING_RULE_NAME); - } - - List<FilterRule> temp = new ArrayList<>(); - for (FilterRule rule : this.rules) { - if (rule.name.equals(name)) { - temp.add(rule); - } - } - this.rules.removeAll(temp); - } - - /** - * Delete rule. - * - * @param name name - * @param regex regex - */ - public void deleteRule(String name, String regex) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException(MISSING_RULE_NAME); - } - - String nonNullRegex = regex; - if (regex == null || regex.isEmpty()) { - nonNullRegex = ".*"; + public static List<String> filter(String json, String expression) { + if (json == null || json.isEmpty()) { + throw new IllegalArgumentException("a json string must be provided"); } - List<FilterRule> temp = new ArrayList<>(); - for (FilterRule rule : this.rules) { - if (rule.name.equals(name) && rule.getRegex().equals(nonNullRegex)) { - temp.add(rule); - } + if (expression == null || expression.isEmpty()) { + throw new IllegalArgumentException("an expression must be provided"); } - this.rules.removeAll(temp); - } - - /** - * Add rule. - * - * @param name name - * @param regex regex - */ - public void addRule(String name, String regex) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException(MISSING_RULE_NAME); - } + Configuration conf = Configuration.defaultConfiguration().addOptions(Option.ALWAYS_RETURN_LIST); + DocumentContext document = JsonPath.using(conf).parse(json); - String nonNullRegex = regex; - if (regex == null || regex.isEmpty()) { - nonNullRegex = ".*"; + List<String> matches = new ArrayList<>(); + try { + matches = document.read(expression); + } catch (Exception e) { + logger.error("JsonPath couldn't read {} because of {}", expression, e.getMessage(), e); } - for (FilterRule rule : this.rules) { - if (rule.getName().equals(name) && rule.getRegex().equals(regex)) { - return; - } + if (matches.isEmpty()) { + logger.warn("Could not find any matches for rule {} in json {}", expression, json); } - this.rules.add(new FilterRule(name, nonNullRegex)); + return matches; } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("JsonProtocolFilter [rules=").append(rules).append("]"); - return builder.toString(); - } - } diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java index f125c134..394e73af 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java @@ -31,7 +31,6 @@ import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; - import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -168,7 +167,7 @@ public abstract class ProtocolCoderToolset { /** * remove coder. - * + * * @param eventClass event class */ public void removeCoders(String eventClass) { @@ -206,7 +205,7 @@ public abstract class ProtocolCoderToolset { /** * Get group id. - * + * * @return the groupId */ public String getGroupId() { @@ -215,7 +214,7 @@ public abstract class ProtocolCoderToolset { /** * Get artifact id. - * + * * @return the artifactId */ public String getArtifactId() { @@ -224,7 +223,7 @@ public abstract class ProtocolCoderToolset { /** * Get custom coder. - * + * * @return the customCoder */ public CustomCoder getCustomCoder() { @@ -233,7 +232,7 @@ public abstract class ProtocolCoderToolset { /** * Set custom coder. - * + * * @param customCoder the customCoder to set. */ public void setCustomCoder(CustomCoder customCoder) { @@ -262,28 +261,14 @@ public abstract class ProtocolCoderToolset { throw new IllegalStateException("No coders available"); } - if (this.coders.size() == 1) { - final JsonProtocolFilter filter = this.coders.get(0).getFilter(); - if (!filter.isRules()) { - return this.coders.get(0); - } - } - - JsonElement event; - try { - event = this.filteringParser.parse(json); - } catch (final Exception e) { - throw new UnsupportedOperationException(e); - } - for (final CoderFilters decoder : this.coders) { try { - final boolean accepted = decoder.getFilter().accept(event); + boolean accepted = decoder.getFilter().accept(json); if (accepted) { return decoder; } } catch (final Exception e) { - logger.info("{}: unexpected failure accepting {} because of {}", this, event, + logger.info("{}: unexpected failure accepting {} because of {}", this, json, e.getMessage(), e); // continue } @@ -325,8 +310,6 @@ public abstract class ProtocolCoderToolset { } } - - /** * Tools used for encoding/decoding using GSON. */ diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java index 64fd6823..cbe2b339 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java +++ b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-management * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,6 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; -import java.util.regex.Pattern; - import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; @@ -51,7 +49,6 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; - import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.endpoints.event.comm.TopicSource; @@ -67,7 +64,6 @@ import org.onap.policy.drools.properties.DroolsProperties; import org.onap.policy.drools.protocol.coders.EventProtocolCoder; import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; -import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; import org.onap.policy.drools.protocol.coders.ProtocolCoderToolset; import org.onap.policy.drools.protocol.configuration.ControllerConfiguration; import org.onap.policy.drools.protocol.configuration.PdpdConfiguration; @@ -77,7 +73,6 @@ import org.onap.policy.drools.utils.logging.LoggerUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Telemetry JAX-RS Interface to the PDP-D. */ @@ -98,7 +93,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -111,7 +106,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -132,7 +127,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -154,7 +149,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -175,7 +170,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -187,7 +182,7 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST @@ -216,7 +211,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -229,7 +224,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -242,7 +237,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -257,7 +252,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -274,7 +269,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -287,7 +282,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -315,7 +310,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -343,7 +338,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -364,7 +359,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -385,7 +380,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -398,7 +393,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -411,7 +406,7 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST @@ -479,7 +474,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -492,7 +487,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -506,7 +501,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -528,7 +523,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -557,7 +552,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -604,7 +599,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -632,7 +627,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -644,7 +639,7 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST @@ -688,7 +683,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -701,7 +696,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -724,7 +719,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -747,7 +742,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -775,7 +770,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -807,7 +802,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -836,7 +831,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -875,7 +870,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -928,7 +923,7 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST @@ -985,7 +980,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -1027,7 +1022,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -1085,29 +1080,21 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST - @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}") + @Path("engine/controllers/tools/coders/decoders/filters/rule") @ApiOperation(value = "Produces a Decoder Rule Filter in a format that the Policy Controller can understand", notes = "The result can be used with other APIs to attach a filter to a decoder") public Response rules( - @ApiParam(value = "Negate regex?", - required = true) @DefaultValue("false") @QueryParam("negate") boolean negate, - @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String name, - @ApiParam(value = "Regex expression", required = true) String regex) { - String literalRegex = Pattern.quote(regex); - if (negate) { - literalRegex = "^(?!" + literalRegex + "$).*"; - } - - return Response.status(Status.OK).entity(new JsonProtocolFilter.FilterRule(name, literalRegex)).build(); + @ApiParam(value = "JsonPath expression", required = true) String expression) { + return Response.status(Status.OK).entity(new JsonProtocolFilter(expression)).build(); } /** * GET. - * + * * @return response object */ @GET @@ -1142,7 +1129,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1178,7 +1165,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1215,7 +1202,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1258,7 +1245,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1303,7 +1290,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -1359,17 +1346,16 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") - @ApiOperation(value = "Gets the filter rules attached to a topic decoder of a controller", + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rule") + @ApiOperation(value = "Gets the filter rule attached to a topic decoder of a controller", notes = "Decoders are associated with networked topics. A Policy Controller manages " + "multiple topics and therefore its attached decoders. " + "A Policy Controller uses filters to further specify the fact mapping. " - + "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer = "List", response = FilterRule.class) + + "Filters are applied on a per fact type using a jsonpath expression rule. ") @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"), @ApiResponse(code = 406, message = "The system is an administrative state that prevents " + "this request to be fulfilled")}) @@ -1394,7 +1380,7 @@ public class RestManager { .entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")).build(); } - return Response.status(Response.Status.OK).entity(filter.getRules()).build(); + return Response.status(Response.Status.OK).entity(filter.getRule()).build(); } catch (final IllegalArgumentException e) { logger.debug("{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}", this, controllerName, topic, factClass, e.getMessage(), e); @@ -1409,86 +1395,25 @@ public class RestManager { } /** - * GET. - * - * @return response object - */ - @GET - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") - @ApiOperation(value = "Gets a filter rule by name attached to a topic decoder of a controller", - notes = "Decoders are associated with networked topics. A Policy Controller manages " - + "multiple topics and therefore its attached decoders. " - + "A Policy Controller uses filters to further specify the fact mapping. " - + "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer = "List", response = FilterRule.class) - @ApiResponses(value = { - @ApiResponse(code = 404, message = "The controller, topic, fact type, or rule name cannot be found"), - @ApiResponse(code = 406, - message = "The system is an administrative state that prevents " + "this request to be fulfilled")}) - public Response decoderFilterRules( - @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, - @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic, - @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass, - @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName) { - try { - final DroolsController drools = this.getDroolsController(controllerName); - final ProtocolCoderToolset decoder = - EventProtocolCoder.manager.getDecoders(drools.getGroupId(), drools.getArtifactId(), topic); - - final CoderFilters filters = decoder.getCoder(factClass); - if (filters == null) { - return Response.status(Response.Status.BAD_REQUEST) - .entity(new Error(controllerName + ":" + topic + ":" + factClass + " does not exist")).build(); - } - - final JsonProtocolFilter filter = filters.getFilter(); - if (filter == null) { - return Response.status(Response.Status.BAD_REQUEST) - .entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")).build(); - } - - return Response.status(Response.Status.OK).entity(filter.getRules(ruleName)).build(); - } catch (final IllegalArgumentException e) { - logger.debug( - "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); - return Response.status(Response.Status.NOT_FOUND) - .entity(new Error(controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found")) - .build(); - } catch (final IllegalStateException e) { - logger.debug( - "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); - return Response.status(Response.Status.NOT_ACCEPTABLE) - .entity(new Error( - controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable")) - .build(); - } - } - - /** * DELETE. - * + * * @return response object */ @DELETE - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}") - @ApiOperation(value = "Deletes a filter rule by name attached to a topic decoder of a controller", + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rule") + @ApiOperation(value = "Deletes the filter rule attached to a topic decoder of a controller", notes = "Decoders are associated with networked topics. A Policy Controller manages " + "multiple topics and therefore its attached decoders. " + "A Policy Controller uses filters to further specify the fact mapping. " - + "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer = "List", response = FilterRule.class) + + "Filters are applied on a per fact type using a jsonpath expression rule. ") @ApiResponses(value = { - @ApiResponse(code = 404, message = "The controller, topic, fact type, or rule name cannot be found"), + @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"), @ApiResponse(code = 406, message = "The system is an administrative state that prevents " + "this request to be fulfilled")}) public Response decoderFilterRuleDelete( @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic, - @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass, - @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName, - @ApiParam(value = "Filter Rule", required = true) FilterRule rule) { + @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass) { try { final DroolsController drools = this.getDroolsController(controllerName); @@ -1507,50 +1432,38 @@ public class RestManager { .entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")).build(); } - if (rule == null) { - filter.deleteRules(ruleName); - return Response.status(Response.Status.OK).entity(filter.getRules()).build(); - } - - if (rule.getName() == null || !rule.getName().equals(ruleName)) { - return Response.status(Response.Status.BAD_REQUEST).entity(new Error(controllerName + ":" + topic + ":" - + factClass + ":" + ruleName + " rule name request inconsistencies (" + rule.getName() + ")")) - .build(); - } - - filter.deleteRule(ruleName, rule.getRegex()); - return Response.status(Response.Status.OK).entity(filter.getRules()).build(); + filter.setRule(null); + return Response.status(Response.Status.OK).entity(filter.getRule()).build(); } catch (final IllegalArgumentException e) { logger.debug( - "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); + "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}", + this, controllerName, topic, factClass, e.getMessage(), e); return Response.status(Response.Status.NOT_FOUND) - .entity(new Error(controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found")) + .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")) .build(); } catch (final IllegalStateException e) { logger.debug( - "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); + "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}", + this, controllerName, topic, factClass, e.getMessage(), e); return Response.status(Response.Status.NOT_ACCEPTABLE) .entity(new Error( - controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable")) + controllerName + ":" + topic + ":" + factClass + " not acceptable")) .build(); } } /** * PUT. - * + * * @return response object */ @PUT - @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules") + @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rule") @ApiOperation(value = "Places a new filter rule in a topic decoder", notes = "Decoders are associated with networked topics. A Policy Controller manages " + "multiple topics and therefore its attached decoders. " + "A Policy Controller uses filters to further specify the fact mapping. " - + "Filters are applied on a per fact type and are composed of field matching rules. ", - responseContainer = "List", response = FilterRule.class) + + "Filters are applied on a per fact type using a jsonpath expression rule. ") @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"), @ApiResponse(code = 406, message = "The system is an administrative state that prevents " + "this request to be fulfilled")}) @@ -1558,8 +1471,7 @@ public class RestManager { @ApiParam(value = "Policy Controller Name", required = true) @PathParam("controller") String controllerName, @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic, @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass, - @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName, - @ApiParam(value = "Filter Rule", required = true) FilterRule rule) { + @ApiParam(value = "JsonPath filter expression", required = true) String rule) { try { final DroolsController drools = this.getDroolsController(controllerName); @@ -1578,25 +1490,25 @@ public class RestManager { .entity(new Error(controllerName + ":" + topic + ":" + factClass + " no filters")).build(); } - if (rule.getName() == null) { + if (rule == null || rule.isEmpty()) { return Response.status(Response.Status.BAD_REQUEST).entity(new Error(controllerName + ":" + topic + ":" - + factClass + " rule name request inconsistencies (" + rule.getName() + ")")).build(); + + factClass + " no filter rule provided")).build(); } - filter.addRule(rule.getName(), rule.getRegex()); - return Response.status(Response.Status.OK).entity(filter.getRules()).build(); + filter.setRule(rule); + return Response.status(Response.Status.OK).entity(filter.getRule()).build(); } catch (final IllegalArgumentException e) { logger.debug( "{}: cannot access decoder filter rules for policy-controller {} " - + "topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); + + "topic {} type {} because of {}", + this, controllerName, topic, factClass, e.getMessage(), e); return Response.status(Response.Status.NOT_FOUND) - .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build(); + .entity(new Error(controllerName + ":" + topic + " not found")).build(); } catch (final IllegalStateException e) { logger.debug( "{}: cannot access decoder filter rules for policy-controller {} " - + "topic {} type {} rule {} because of {}", - this, controllerName, topic, factClass, ruleName, e.getMessage(), e); + + "topic {} type {} because of {}", + this, controllerName, topic, factClass, e.getMessage(), e); return Response.status(Response.Status.NOT_ACCEPTABLE) .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable")).build(); } @@ -1604,7 +1516,7 @@ public class RestManager { /** * POST. - * + * * @return response object */ @POST @@ -1665,7 +1577,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1715,7 +1627,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -1735,7 +1647,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -1755,7 +1667,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1768,7 +1680,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1781,7 +1693,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1794,7 +1706,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1807,7 +1719,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1820,7 +1732,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1833,7 +1745,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1847,7 +1759,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1861,7 +1773,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1876,7 +1788,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1890,7 +1802,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1905,7 +1817,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1920,7 +1832,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1936,7 +1848,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1951,7 +1863,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1964,7 +1876,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1977,7 +1889,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -1991,7 +1903,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -2004,7 +1916,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -2024,7 +1936,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -2048,7 +1960,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -2061,7 +1973,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -2081,7 +1993,7 @@ public class RestManager { /** * DELETE. - * + * * @return response object */ @DELETE @@ -2102,7 +2014,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -2146,7 +2058,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT @@ -2190,7 +2102,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -2203,7 +2115,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -2227,7 +2139,7 @@ public class RestManager { /** * GET. - * + * * @return response object */ @GET @@ -2255,7 +2167,7 @@ public class RestManager { /** * PUT. - * + * * @return response object */ @PUT diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java index e83e5880..e0baeb6d 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,205 +24,140 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; -import java.util.List; - import org.junit.Test; -import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; -import org.onap.policy.drools.utils.Pair; - public class JsonProtocolFilterTest { - private static final String NAME1 = "name1"; - private static final String REGEX1 = "regex1"; + private static final String JSON = + "{\"requestID\":\"38adde30-cc22-11e8-a8d5-f2801f1b9fd1\",\"entity\":\"controller\"," + + "\"controllers\":[{\"name\":\"test-controller\"," + + "\"drools\":{\"groupId\":\"org.onap.policy.drools.test\"," + + "\"artifactId\":\"test\",\"version\":\"0.0.1\"},\"operation\":\"update\"}]}"; + + /** + * Tests getting the rule expression of the filter. + */ + @Test + public void getRuleTest() { + assertEquals("$.test", new JsonProtocolFilter("$.test").getRule()); + } + + /** + * Tests setting the rule expression of the filter. + */ + @Test + public void setRuleTest() { + JsonProtocolFilter filter = new JsonProtocolFilter(); + assertEquals(JsonProtocolFilter.MATCH_ANY, filter.getRule()); + filter.setRule("$.test"); + assertEquals("$.test", filter.getRule()); + } + + /** + * Tests that the rule expression will be set to match anything if an empty string is passed. + */ + @Test + public void setRuleEmptyTest() { + assertEquals(JsonProtocolFilter.MATCH_ANY, new JsonProtocolFilter("").getRule()); + } + + /** + * Tests that the rule expression will be set to match anything if a null string is passed. + */ + @Test + public void setRuleNullTest() { + assertEquals(JsonProtocolFilter.MATCH_ANY, new JsonProtocolFilter(null).getRule()); + } + + /** + * Tests accepting a message if all filter rules pass. + */ + @Test + public void acceptPassTest() { + assertTrue(new JsonProtocolFilter( + "$.controllers[?(@.drools.version =~ /\\d\\.\\d\\.\\d/ && @.operation == 'update')]") + .accept(JSON)); + } + + /** + * Tests accepting a message without having to filter if the rule is set to match anything. + */ + @Test + public void acceptAnyTest() { + assertTrue(new JsonProtocolFilter(null).accept(JSON)); + } - private static final String NAME2 = "name2"; - private static final String REGEX2 = "regex2"; + /** + * Tests rejecting a message if one or more of the filter rules fail. + */ + @Test + public void acceptFailTest() { + assertFalse( + new JsonProtocolFilter("$.controllers[?(@.drools.version =~ /\\\\d\\\\.\\\\d\\\\.2/)]") + .accept(JSON)); + } - private static final String NAME3 = "name3"; - private static final String REGEX3 = "regex3"; + /** + * Tests finding field matches for a filter rule corresponding to a topic. + */ + @Test + public void filterPassTest() { + assertEquals("38adde30-cc22-11e8-a8d5-f2801f1b9fd1", new JsonProtocolFilter("$.requestID").filter(JSON).get(0)); + } + + /** + * Tests that an empty list is returned when no matches are found. + */ + @Test + public void filterFailTest() { + assertTrue(new JsonProtocolFilter("$.test").filter(JSON).isEmpty()); + } - private static final String NAME4 = "name4"; - private static final String REGEX4a = "^regex4a.*"; - private static final String REGEX4b = ".*regex4b$"; - + /** + * Tests static method for filtering a JSON string with an arbitrary expression. + */ + @Test + public void staticFilterPassTest() { + assertEquals("controller", JsonProtocolFilter.filter(JSON, "$.entity").get(0)); + } + /** + * Tests that an empty list is returned when the static filter() method does not find any matches. + */ @Test - public void test() { - - // ******************** D E F I N E f i l t e r R u l e O b j e c t s *************************** - // DEFINE one (1) filterRule object (using constructor without parms passed; instead use set methods - FilterRule filterRule1 = new FilterRule(); - filterRule1.setName(NAME1); - filterRule1.setRegex(REGEX1); - assertEquals(filterRule1.getName(), NAME1); - assertEquals(filterRule1.getRegex(), REGEX1); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // DEFINE four (4) filterRule objects (using constructor passing the field values - FilterRule filterRule2 = new FilterRule(NAME2, REGEX2); - assertEquals(filterRule2.getName(), NAME2); - assertEquals(filterRule2.getRegex(), REGEX2); - - FilterRule filterRule3 = new FilterRule(NAME3, REGEX3); - assertEquals(filterRule3.getName(), NAME3); - assertEquals(filterRule3.getRegex(), REGEX3); - - FilterRule filterRule4a = new FilterRule(NAME4, REGEX4a); - assertEquals(filterRule4a.getName(), NAME4); - assertEquals(filterRule4a.getRegex(), REGEX4a); - - FilterRule filterRule4b = new FilterRule(NAME4, REGEX4b); - assertEquals(filterRule4b.getName(), NAME4); - assertEquals(filterRule4b.getRegex(), REGEX4b); - - - - // ************************ D E F I N E f i l t e r L i s t s ************************************ - // DEFINE rawFiltersA - List<Pair<String,String>> rawFiltersA = new ArrayList<>(); - rawFiltersA.add(new Pair<String,String>(filterRule1.getName(), filterRule1.getRegex())); - rawFiltersA.add(new Pair<String,String>(filterRule2.getName(), filterRule2.getRegex())); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // DEFINE filtersA - List<FilterRule> filtersA = new ArrayList<>(); - for (Pair<String, String> filterPair: rawFiltersA) { - if (filterPair.first() == null || filterPair.first().isEmpty()) { - continue; - } - filtersA.add(new FilterRule(filterPair.first(), filterPair.second())); - } - - - - // *********** I N S T A N T I A T E J s o n P r o t o c o l F i l t e r O b j e c t s ********** - // INSTANTIATE protocolFilterA (passing raw filters to the 'fromRawFilters' constructor) - JsonProtocolFilter protocolFilterA = JsonProtocolFilter.fromRawFilters(rawFiltersA); - assertTrue(protocolFilterA.isRules()); - assertEquals(protocolFilterA.getRules().toString(), filtersA.toString()); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // INSTANTIATE protocolFilterB (passing filters list to constructor which accepts such) - JsonProtocolFilter protocolFilterB = new JsonProtocolFilter(filtersA); - assertTrue(protocolFilterB.isRules()); - assertEquals(protocolFilterB.getRules(), filtersA); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // INSTANTIATE protocolFilterC (using constructor without parms; add instead using setRules() method - JsonProtocolFilter protocolFilterC = new JsonProtocolFilter(); - protocolFilterC.setRules(filtersA); - assertTrue(protocolFilterC.isRules()); - assertEquals(protocolFilterC.getRules(), filtersA); - - - - // *** D E F I N E o t h e r f i l t e r L i s t s f o r v a l i d a t i o n s ************ - // DEFINE rawFiltersB - List<Pair<String,String>> rawFiltersB = new ArrayList<>(); - rawFiltersB.add(new Pair<String,String>(filterRule1.getName(), filterRule1.getRegex())); - rawFiltersB.add(new Pair<String,String>(filterRule2.getName(), filterRule2.getRegex())); - rawFiltersB.add(new Pair<String,String>(filterRule3.getName(), filterRule3.getRegex())); - rawFiltersB.add(new Pair<String,String>(filterRule4a.getName(), filterRule4a.getRegex())); - rawFiltersB.add(new Pair<String,String>(filterRule4b.getName(), filterRule4b.getRegex())); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // DEFINE filtersB - List<FilterRule> filtersB = new ArrayList<>(); - for (Pair<String, String> filterPair: rawFiltersB) { - filtersB.add(new FilterRule(filterPair.first(), filterPair.second())); - } - - - - // *********** A D D T O p r o t o c o l F i l t e r B 3 m o r e f i l t e r s ************ - protocolFilterB.addRule(filterRule3.getName(), filterRule3.getRegex()); - protocolFilterB.addRule(filterRule4a.getName(), filterRule4a.getRegex()); - protocolFilterB.addRule(filterRule4b.getName(), filterRule4b.getRegex()); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // VALIDATE that protocolFilterB now contains filters passed using filtersA and the new ones just added - assertEquals(protocolFilterB.getRules().toString(), filtersB.toString()); - - - - // ************ D E L E T E f i l t e r s f r o m p r o t o c o l F i l t e r B *********** - // DELETE specific filter from protocolFilterB by passing both the name & regex values - - assertTrue(protocolFilterB.getRules(NAME3).size() == 1); - assertTrue(protocolFilterB.getRules(NAME3).get(0).getName().equals(NAME3)); - assertTrue(protocolFilterB.getRules(NAME3).get(0).getRegex().equals(REGEX3)); - - assertTrue(protocolFilterB.getRules(NAME4).size() == 2); - assertTrue(protocolFilterB.getRules(NAME4).get(0).getName().equals(NAME4)); - assertTrue(protocolFilterB.getRules(NAME4).get(0).getRegex().equals(REGEX4a)); - assertTrue(protocolFilterB.getRules(NAME4).get(1).getName().equals(NAME4)); - assertTrue(protocolFilterB.getRules(NAME4).get(1).getRegex().equals(REGEX4b)); - - final String jsonA = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," - + "\"name3\":\"regex3\",\"name4\":\"regex4a\",\"name4\":\"regex4b\"}"; - final String jsonB = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," - + "\"name3\":\"regex3\",\"name4\":\"regex4a-regex4b\"}"; - final String jsonC = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," - + "\"name3\":\"regex3\",\"name4\":\"regex4a\"}"; - final String jsonD = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," - + "\"name3\":\"regex3\",\"name4\":\"regex4b\"}"; - - assertFalse(protocolFilterB.accept(jsonA)); - assertTrue(protocolFilterB.accept(jsonB)); - assertFalse(protocolFilterB.accept(jsonC)); - assertFalse(protocolFilterB.accept(jsonD)); - - protocolFilterB.deleteRule(NAME4, REGEX4a); - - assertTrue(protocolFilterB.accept(jsonA)); - assertTrue(protocolFilterB.accept(jsonB)); - assertFalse(protocolFilterB.accept(jsonC)); - assertTrue(protocolFilterB.accept(jsonD)); - - protocolFilterB.addRule(NAME4, REGEX4a); - - assertTrue(protocolFilterB.getRules(NAME4).size() == 2); - assertTrue(protocolFilterB.getRules(NAME4).get(0).getName().equals(NAME4)); - assertTrue(protocolFilterB.getRules(NAME4).get(0).getRegex().equals(REGEX4b)); - assertTrue(protocolFilterB.getRules(NAME4).get(1).getName().equals(NAME4)); - assertTrue(protocolFilterB.getRules(NAME4).get(1).getRegex().equals(REGEX4a)); - - assertFalse(protocolFilterB.accept(jsonA)); - assertTrue(protocolFilterB.accept(jsonB)); - assertFalse(protocolFilterB.accept(jsonC)); - assertFalse(protocolFilterB.accept(jsonD)); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // DELETE all filters from protocolFilterB that have a match to the same name value - protocolFilterB.deleteRules(NAME4); - - assertTrue(protocolFilterB.getRules(NAME4).isEmpty()); - assertTrue(protocolFilterB.accept(jsonA)); - assertTrue(protocolFilterB.accept(jsonB)); - assertTrue(protocolFilterB.accept(jsonC)); - assertTrue(protocolFilterB.accept(jsonD)); - - assertTrue(protocolFilterB.getRules(NAME3).size() == 1); - protocolFilterB.addRule(NAME3, REGEX3); - assertTrue(protocolFilterB.getRules(NAME3).size() == 1); - protocolFilterB.deleteRule(NAME3, REGEX3); - assertTrue(protocolFilterB.getRules(NAME3).isEmpty()); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // VALIDATE that protocolFilterB now only contains the filters that were originally passed using filtersA - assertEquals(protocolFilterB.getRules(), filtersA); - - // ************ A C C E P T J S O N I F I T P A S S E S A L L F I L T E R S *********** - // ACCEPT TRUE a JSON that passes all filters - String jsonE = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"}"; - assertTrue(protocolFilterA.accept(jsonE)); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ACCEPT FALSE a JSON that does NOT pass all filters - String jsonF = "{ \"name1\":\"regex1\"}"; - assertFalse(protocolFilterA.accept(jsonF)); + public void staticFilterFailTest() { + assertTrue(JsonProtocolFilter.filter(JSON, "$.test").isEmpty()); } + /** + * Tests that an exception is thrown if a null JSON string is passed. + */ + @Test(expected = IllegalArgumentException.class) + public void staticFilterNullJsonTest() { + JsonProtocolFilter.filter(null, "[?($ =~ /.*/"); + } + + /** + * Tests that an exception is thrown if an empty JSON string is passed. + */ + @Test(expected = IllegalArgumentException.class) + public void staticFilterEmptyJsonTest() { + JsonProtocolFilter.filter("", "[?($ =~ /.*/"); + } + + /** + * Tests that an exception is thrown if a null expression string is passed. + */ + @Test(expected = IllegalArgumentException.class) + public void staticFilterNullExpressionTest() { + JsonProtocolFilter.filter("{\"hello\":\"world\"}", null); + } + + /** + * Tests that an exception is thrown if an empty expression string is passed. + */ + @Test(expected = IllegalArgumentException.class) + public void staticFilterEmptyExpressionTest() { + JsonProtocolFilter.filter("{\"hello\":\"world\"}", ""); + } }
\ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java index da491261..b7d72f31 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java @@ -25,7 +25,6 @@ import com.google.gson.GsonBuilder; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.junit.Assert; @@ -39,7 +38,6 @@ import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.controller.internal.MavenDroolsControllerTest; import org.onap.policy.drools.properties.DroolsProperties; import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; -import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; import org.onap.policy.drools.util.KieUtils; import org.onap.policy.drools.utils.Triple; @@ -64,7 +62,7 @@ public class ProtocolCoderToolsetTest { /** * Setup. - * + * * @throws IOException throws IO Exception */ @Before @@ -96,7 +94,7 @@ public class ProtocolCoderToolsetTest { /** * Test the Gson toolset. - * + * * @param protocolFilter protocol filter */ public void testGsonToolset(JsonProtocolFilter protocolFilter) { @@ -157,11 +155,9 @@ public class ProtocolCoderToolsetTest { CoderFilters coderFilters = coderToolset.getCoder(Triple.class.getCanonicalName()); Assert.assertTrue(coderFilters.getCodedClass() == Triple.class.getCanonicalName()); Assert.assertTrue(coderFilters.getFilter() == protocolFilter); - Assert.assertTrue(coderFilters.getFilter().getRules("second").size() == 1); - Assert.assertTrue(coderFilters.getFilter().getRules("third").size() == 1); + Assert.assertTrue(coderFilters.getFilter().getRule() != null); - coderFilters.getFilter().getRules("second").get(0).setRegex("^v2$"); - coderFilters.getFilter().getRules("third").get(0).setRegex(".*v3.*"); + coderFilters.getFilter().setRule("[?($.second =~ /^v2$/ && $.third =~ /.*v3.*/)]"); tripleDecoded = (Triple<String, String, String>) coderToolset.decode(tripleEncoded); @@ -169,8 +165,8 @@ public class ProtocolCoderToolsetTest { Assert.assertTrue(tripleDecoded.second().equals(triple.second())); Assert.assertTrue(tripleDecoded.third().equals(triple.third())); - coderFilters.getFilter().deleteRules("third"); - Assert.assertTrue(coderFilters.getFilter().getRules("third").isEmpty()); + coderFilters.getFilter().setRule(null); + Assert.assertEquals("[?($ =~ /.*/)]", coderFilters.getFilter().getRule()); tripleDecoded = (Triple<String, String, String>) coderToolset.decode(tripleEncoded); @@ -178,7 +174,7 @@ public class ProtocolCoderToolsetTest { Assert.assertTrue(tripleDecoded.second().equals(triple.second())); Assert.assertTrue(tripleDecoded.third().equals(triple.third())); - coderFilters.getFilter().addRule("third", ".*v3.*"); + coderFilters.getFilter().setRule("[?($.third =~ /.*v3.*/)]"); } private String encode(ProtocolCoderToolset coderToolset, Triple<String, String, String> triple) { @@ -188,10 +184,8 @@ public class ProtocolCoderToolsetTest { } private void addRemoveCoder(ProtocolCoderToolset coderToolset) { - List<FilterRule> filters = new ArrayList<>(); - filters.add(new FilterRule("second", ".*")); - - coderToolset.addCoder(this.getClass().getCanonicalName(), new JsonProtocolFilter(filters), 654321); + coderToolset.addCoder(this.getClass().getCanonicalName(), + new JsonProtocolFilter("[?($.second =~ /.*/)]"), 654321); Assert.assertTrue(coderToolset.getCoders().size() == 2); coderToolset.removeCoders(this.getClass().getCanonicalName()); @@ -199,22 +193,18 @@ public class ProtocolCoderToolsetTest { } private void updateCoderFilterRule(ProtocolCoderToolset coderToolset) { - List<FilterRule> filters = new ArrayList<>(); - filters.add(new FilterRule("third", ".*")); - coderToolset.addCoder(Triple.class.getCanonicalName(), new JsonProtocolFilter(filters), 654321); + coderToolset.addCoder(Triple.class.getCanonicalName(), new JsonProtocolFilter("[?($.third =~ /.*/)]"), 654321); Assert.assertTrue(coderToolset.getCoders().size() == 1); Assert.assertTrue(coderToolset.getCoder(Triple.class.getCanonicalName()).getModelClassLoaderHash() == 654321); Assert.assertTrue( - coderToolset.getCoder(Triple.class.getCanonicalName()).getFilter().getRules("third").size() == 1); - - Assert.assertTrue( - coderToolset.getCoder(Triple.class.getCanonicalName()).getFilter().getRules("third").size() == 1); + coderToolset.getCoder( + Triple.class.getCanonicalName()).getFilter().getRule() != null); - Assert.assertTrue(".*".equals(coderToolset.getCoder(Triple.class.getCanonicalName()).getFilter() - .getRules("third").get(0).getRegex())); + Assert.assertTrue("[?($.third =~ /.*/)]".equals(coderToolset.getCoder(Triple.class.getCanonicalName()) + .getFilter().getRule())); } private void validateInitialization(JsonProtocolFilter protocolFilter, ProtocolCoderToolset coderToolset) { @@ -254,11 +244,6 @@ public class ProtocolCoderToolsetTest { } private JsonProtocolFilter createFilterSet() { - List<FilterRule> filters = new ArrayList<>(); - filters.add(new FilterRule("first", ".*")); - filters.add(new FilterRule("second", "^blah.*")); - filters.add(new FilterRule("third", "^hello$")); - - return new JsonProtocolFilter(filters); + return new JsonProtocolFilter("[?($.first =~ /.*/ && $.second =~ /^blah.*/ && $.third =~ /^hello$/)]"); } } @@ -57,6 +57,7 @@ <!-- Project common dependency versions --> <jersey.version>2.25.1</jersey.version> + <json.path.version>2.4.0</json.path.version> <hibernate.core.version>5.2.10.Final</hibernate.core.version> <hibernate.commons.annotations.version>5.0.1.Final</hibernate.commons.annotations.version> <commons.io.version>2.5</commons.io.version> @@ -95,6 +96,11 @@ <version>2.4.0-b31</version> </dependency> <dependency> + <groupId>com.jayway.jsonpath</groupId> + <artifactId>json-path</artifactId> + <version>${json.path.version}</version> + </dependency> + <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-common</artifactId> <version>${jersey.version}</version> |