From f94c995d4d2b5ffd7f7fa7cf6ec10cdcbf4932a7 Mon Sep 17 00:00:00 2001 From: "Threefoot, Jane (jt6620)" Date: Fri, 8 Sep 2017 09:34:19 -0400 Subject: EdgeRules throws descriptive error on invalid rule Also added test coverage, including refactoring of test resources to simplify test suites. Issue-ID: AAI-277 Change-Id: Ibfdc81342a139d121740f10bccc66a7420b61945 Signed-off-by: Threefoot, Jane (jt6620) --- .../aai/dmaap/AAIDmaapEventJMSProducer.java | 17 ++- .../aai/serialization/db/EdgeProperty.java | 6 + .../openecomp/aai/serialization/db/EdgeRules.java | 125 +++++++++++++++++---- 3 files changed, 120 insertions(+), 28 deletions(-) (limited to 'aai-core/src/main') diff --git a/aai-core/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java b/aai-core/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java index 06a4fa0f..89ed9348 100644 --- a/aai-core/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java +++ b/aai-core/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java @@ -23,6 +23,7 @@ package org.openecomp.aai.dmaap; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import org.json.JSONObject; +import org.openecomp.aai.util.AAIConfig; import org.springframework.jms.connection.CachingConnectionFactory; import org.springframework.jms.core.JmsTemplate; @@ -31,14 +32,18 @@ public class AAIDmaapEventJMSProducer { private JmsTemplate jmsTemplate; public AAIDmaapEventJMSProducer() { - this.jmsTemplate = new JmsTemplate(); - this.jmsTemplate.setConnectionFactory(new CachingConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61447"))); - this.jmsTemplate.setDefaultDestination(new ActiveMQQueue("IN_QUEUE")); + if(AAIConfig.get("aai.jms.enable", "true").equals("true")){ + this.jmsTemplate = new JmsTemplate(); + this.jmsTemplate.setConnectionFactory(new CachingConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61447"))); + this.jmsTemplate.setDefaultDestination(new ActiveMQQueue("IN_QUEUE")); + } } public void sendMessageToDefaultDestination(JSONObject finalJson) { - jmsTemplate.convertAndSend(finalJson.toString()); - CachingConnectionFactory ccf = (CachingConnectionFactory)this.jmsTemplate.getConnectionFactory(); - ccf.destroy(); + if(jmsTemplate != null){ + jmsTemplate.convertAndSend(finalJson.toString()); + CachingConnectionFactory ccf = (CachingConnectionFactory) this.jmsTemplate.getConnectionFactory(); + ccf.destroy(); + } } } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java index 29461bcf..21f07451 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java @@ -21,10 +21,16 @@ package org.openecomp.aai.serialization.db; public enum EdgeProperty { + FROM("from"), + TO("to"), + LABEL("label"), + DIRECTION("direction"), + MULTIPLICITY("multiplicity"), CONTAINS("contains-other-v"), DELETE_OTHER_V("delete-other-v"), SVC_INFRA("SVC-INFRA"), PREVENT_DELETE("prevent-delete"); + private final String name; private EdgeProperty(String name) { diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java index 0aeafabc..22a94554 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java @@ -40,7 +40,6 @@ import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.openecomp.aai.db.props.AAIProperties; -import org.openecomp.aai.dbmodel.DbEdgeRules; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Version; import org.openecomp.aai.serialization.db.exceptions.EdgeMultiplicityException; @@ -58,8 +57,6 @@ public class EdgeRules { private EELFLogger logger = EELFManager.getInstance().getLogger(EdgeRules.class); - private Multimap deleteScope = DbEdgeRules.DefaultDeleteScope; - private DocumentContext rulesDoc; /** @@ -74,22 +71,28 @@ public class EdgeRules { } + private EdgeRules(String rulesFilename) { + String json = this.getEdgeRuleJson(rulesFilename); + rulesDoc = JsonPath.parse(json); + } + + private String getEdgeRuleJson(String rulesFilename) { + InputStream is = getClass().getResourceAsStream(rulesFilename); + + Scanner scanner = new Scanner(is); + String json = scanner.useDelimiter("\\Z").next(); + scanner.close(); + + return json; + } + /** * Loads the versioned DbEdgeRules json file for later parsing. */ @SuppressWarnings("unchecked") private EdgeRules(Version version) { - String json = this.getEdgeRuleJson(version); rulesDoc = JsonPath.parse(json); - - if (!Version.isLatest(version)) { - try { - Class dbEdgeRules = Class.forName("org.openecomp.aai.dbmodel." + version.toString() + ".gen.DbEdgeRules"); - this.deleteScope = (Multimap)dbEdgeRules.getDeclaredField("DefaultDeleteScope").get(null); - } catch (Exception e) { - } - } } private String getEdgeRuleJson(Version version) { @@ -105,6 +108,11 @@ public class EdgeRules { private static class Helper { private static final EdgeRules INSTANCE = new EdgeRules(); private static final Map INSTANCEMAP = new ConcurrentHashMap<>(); + + private static EdgeRules getEdgeRulesByFilename(String rulesFilename) { + return new EdgeRules(rulesFilename); + } + private static EdgeRules getVersionedEdgeRules(Version v) { if (Version.isLatest(v)) { return INSTANCE; @@ -136,6 +144,16 @@ public class EdgeRules { } + /** + * Loads edge rules from the given file. + * + * @param rulesFilename - name of the file to load rules from + * @return the EdgeRules instance + */ + public static EdgeRules getInstance(String rulesFilename) { + return Helper.getEdgeRulesByFilename(rulesFilename); + } + /** * Adds the tree edge. * @@ -252,8 +270,8 @@ public class EdgeRules { where("from").is(nodeB).and("to").is(nodeA) ); - List results = rulesDoc.read("$.rules.[?]", aToB); - results.addAll(rulesDoc.read("$.rules.[?]", bToA)); + List> results = readRules(aToB); + results.addAll(readRules(bToA)); return !results.isEmpty(); @@ -300,6 +318,8 @@ public class EdgeRules { return result; } + + /** * Gets the edge rule of the given type that exists between A and B. * Will check B|A as well, and flips the direction accordingly if that succeeds @@ -313,19 +333,21 @@ public class EdgeRules { */ public EdgeRule getEdgeRule(EdgeType type, String nodeA, String nodeB) throws AAIException { //try A to B - List> aToBEdges = rulesDoc.read("$.rules.[?]", buildFilter(type, nodeA, nodeB)); + List> aToBEdges = readRules(buildFilter(type, nodeA, nodeB)); if (!aToBEdges.isEmpty()) { //lazily stop iterating if we find a match //should there be a mismatch between type and isParent, //the caller will receive something. //this operates on the assumption that there are at most two rules //for a given vertex pair + verifyRule(aToBEdges.get(0)); return buildRule(aToBEdges.get(0)); } //we get here if there was nothing for A to B, so let's try B to A - List> bToAEdges = rulesDoc.read("$.rules.[?]", buildFilter(type, nodeB, nodeA)); + List> bToAEdges = readRules(buildFilter(type, nodeB, nodeA)); if (!bToAEdges.isEmpty()) { + verifyRule(bToAEdges.get(0)); return flipDirection(buildRule(bToAEdges.get(0))); //bc we need to return as A|B, so flip the direction to match } @@ -467,6 +489,61 @@ public class EdgeRules { } + /** + * Verifies that all required properties are defined in the given edge rule. + * If they are not, throws a RuntimeException. + * + * @param rule - Map representing + * an edge rule + */ + private void verifyRule(Map rule) { + for (EdgeProperty prop : EdgeProperty.values()) { + if (!rule.containsKey(prop.toString())) { + /* Throws RuntimeException as rule definition errors + * cannot be recovered from, and should never happen anyway + * because these are configuration files, so requiring all + * downstream code to check for this exception seems inappropriate. + * It's instantiated with an AAIException to make sure all + * relevant information is present in the error message. + */ + throw new RuntimeException(new AAIException("AAI_4005", + "Rule between " + rule.get("from") + " and " + rule.get("to") + + " is missing property " + prop + ".")); + } + } + } + + /** + * Reads all the edge rules from the loaded json file. + * + * @return List> + * Each map represents a rule read from the json. + */ + private List> readRules() { + return readRules(null); + } + + /** + * Reads the edge rules from the loaded json file, using the given filter + * to get specific rules. If filter is null, will get all rules. + * + * @param filter - may be null to indicate get all + * @return List> + * Each map represents a rule read from the json. + */ + private List> readRules(Filter filter) { + List> results; + if (filter == null) { //no filter means get all + results = rulesDoc.read("$.rules.*"); + } else { + results = rulesDoc.read("$.rules.[?]", filter); + } + for (Map result : results) { + verifyRule(result); + } + return results; + } + /** * Gets all the edge rules we define. * @@ -475,7 +552,7 @@ public class EdgeRules { public Multimap getAllRules() { Multimap result = ArrayListMultimap.create(); - List> rules = rulesDoc.read("$.rules.*"); + List> rules = readRules(); for (Map rule : rules) { EdgeRule er = buildRule(rule); String name = rule.get("from") + "|" + rule.get("to"); @@ -485,19 +562,23 @@ public class EdgeRules { return result; } - public Multimap getDeleteSemantics() { - return this.deleteScope; - } - + /** + * Gets all edge rules that define a child relationship from + * the given node type. + * + * @param nodeType + * @return + */ public Set getChildren(String nodeType) { final Filter filter = filter( where("from").is(nodeType).and(EdgeProperty.CONTAINS.toString()).is("${direction}") ).or(where("to").is(nodeType).and(EdgeProperty.CONTAINS.toString()).is("!${direction}")); - final List> rules = rulesDoc.read("$.rules.[?]", filter); + final List> rules = readRules(filter); final Set result = new HashSet<>(); rules.forEach(item -> { + verifyRule(item); result.add(buildRule(item)); }); -- cgit 1.2.3-korg