summaryrefslogtreecommitdiffstats
path: root/aai-core/src/main/java
diff options
context:
space:
mode:
authorMaharajh, Robby (rx2202) <rx2202@att.com>2017-12-01 10:41:41 -0500
committerMaharajh, Robby (rx2202) <rx2202@att.com>2017-12-01 10:45:31 -0500
commit2e4f21dea97049f4de34fcfd789f461882e24602 (patch)
tree72696b56796bd32990bb9b3f241036d20e6ed550 /aai-core/src/main/java
parent8dcb9900cae95a17ca6d029a665d512b3e7b11a2 (diff)
Added support for Multiple Edges
Issue-ID: AAI-524 Change-Id: I33dd31315992e2efb2d6d390ffc523655b55a84c Signed-off-by: Maharajh, Robby (rx2202) <rx2202@att.com>
Diffstat (limited to 'aai-core/src/main/java')
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java220
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java165
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java32
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java10
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java99
-rw-r--r--aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java35
-rw-r--r--aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java5
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java266
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/EdgeProperty.java19
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRule.java34
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRules.java611
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/MultipleEdgeRuleFoundException.java40
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/NoEdgeRuleFoundException.java6
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/util/VersionChecker.java39
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java31
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/queryformats/exceptions/AAIFormatQueryResultFormatNotSupported.java40
16 files changed, 1184 insertions, 468 deletions
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java
index 8a585dae..82079ad7 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java
@@ -22,9 +22,8 @@
package org.onap.aai.query.builder;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -78,6 +77,18 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
* Instantiates a new graph traversal builder.
*
* @param loader the loader
+ */
+ public GraphTraversalBuilder(Loader loader, GraphTraversalSource source, EdgeRules edgeRules) {
+ super(loader, source);
+ this.edgeRules = edgeRules;
+ traversal = (GraphTraversal<Vertex, E>) __.<E>start();
+
+ }
+
+ /**
+ * Instantiates a new graph traversal builder.
+ *
+ * @param loader the loader
* @param start the start
*/
public GraphTraversalBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
@@ -86,34 +97,28 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
traversal = (GraphTraversal<Vertex, E>) __.__(start);
}
-
- /**
- * @{inheritDoc}
- */
- @Override
- public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
- return this.getVerticesByProperty(key, value);
- }
-
/**
- * @{inheritDoc}
+ * Instantiates a new graph traversal builder.
+ *
+ * @param loader the loader
+ * @param start the start
*/
- @Override
- public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
- return this.getVerticesByProperty(key, values);
+ public GraphTraversalBuilder(Loader loader, GraphTraversalSource source, Vertex start, EdgeRules edgeRules) {
+ super(loader, source, start);
+ this.edgeRules = edgeRules;
+ traversal = (GraphTraversal<Vertex, E>) __.__(start);
+
}
-
+
/**
* @{inheritDoc}
*/
@Override
public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) {
- //this is because the index is registered as an Integer
- value = this.correctObjectType(value);
-
- traversal.has(key, value);
+ // correct value call because the index is registered as an Integer
+ traversal.has(key, this.correctObjectType(value));
stepIndex++;
return (QueryBuilder<Vertex>) this;
@@ -151,10 +156,10 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
* @{inheritDoc}
*/
@Override
- public QueryBuilder<Vertex> getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
+ public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) {
- for (String key : map.keySet()) {
- traversal.has(key, map.get(key));
+ for (Map.Entry<String, String> es : map.entrySet()) {
+ traversal.has(es.getKey(), es.getValue());
stepIndex++;
}
traversal.has(AAIProperties.NODE_TYPE, type);
@@ -166,16 +171,6 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
* @{inheritDoc}
*/
@Override
- public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
- this.createKeyQuery(obj);
- this.createContainerQuery(obj);
- return (QueryBuilder<Vertex>) this;
- }
-
- /**
- * @{inheritDoc}
- */
- @Override
public QueryBuilder<Vertex> createKeyQuery(Introspector obj) {
Set<String> keys = obj.getKeys();
Object val;
@@ -257,70 +252,78 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
* @{inheritDoc}
*/
@Override
- public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
+ public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException {
String isAbstractType = parent.getMetadata(ObjectMetadata.ABSTRACT);
if ("true".equals(isAbstractType)) {
markParentBoundary();
traversal.union(handleAbstractEdge(type, parent, child));
- stepIndex += 1;
+ stepIndex++;
} else {
- this.edgeQueryToVertex(type, parent, child);
+ this.edgeQueryToVertex(type, parent, child, null);
}
return (QueryBuilder<Vertex>) this;
}
-
+
+ /**
+ *
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException {
+ this.edgeQueryToVertex(type, out, in, labels);
+ return (QueryBuilder<Vertex>) this;
+ }
+
+
private Traversal<Vertex, Vertex>[] handleAbstractEdge(EdgeType type, Introspector abstractParent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
String childName = child.getDbName();
String inheritorMetadata = abstractParent.getMetadata(ObjectMetadata.INHERITORS);
String[] inheritors = inheritorMetadata.split(",");
- Traversal<Vertex, Vertex>[] unionTraversals = new Traversal[inheritors.length];
- int traversalIndex = 0;
+ List<Traversal<Vertex, Vertex>> unionTraversals = new ArrayList<>(inheritors.length);
+
for (int i = 0; i < inheritors.length; i++) {
String inheritor = inheritors[i];
if (edgeRules.hasEdgeRule(inheritor, childName) || edgeRules.hasEdgeRule(childName, inheritor)) {
- EdgeRule rule = edgeRules.getEdgeRule(type, inheritor, childName);
+ Map<String, EdgeRule> rules = edgeRules.getEdgeRules(type, inheritor, childName);
GraphTraversal<Vertex, Vertex> innerTraversal = __.start();
- if (rule.getDirection().equals(Direction.OUT)) {
- innerTraversal.out(rule.getLabel());
- } else {
- innerTraversal.in(rule.getLabel());
+
+ final List<String> inLabels = new ArrayList<>();
+ final List<String> outLabels = new ArrayList<>();
+
+ rules.forEach((k,v) -> {
+ if (v.getDirection().equals(Direction.IN)) {
+ inLabels.add(k);
+ } else {
+ outLabels.add(k);
+ }
+ } );
+
+ if (inLabels.isEmpty() && !outLabels.isEmpty()) {
+ innerTraversal.out(outLabels.toArray(new String[outLabels.size()]));
+ } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
+ innerTraversal.in(inLabels.toArray(new String[inLabels.size()]));
+ } else {
+ innerTraversal.union(__.out(outLabels.toArray(new String[outLabels.size()])), __.in(inLabels.toArray(new String[inLabels.size()])));
}
+
innerTraversal.has(AAIProperties.NODE_TYPE, childName);
- unionTraversals[traversalIndex] = innerTraversal;
- traversalIndex++;
+ unionTraversals.add(innerTraversal);
}
}
- if (traversalIndex < inheritors.length) {
- Traversal<Vertex, Vertex>[] temp = Arrays.copyOfRange(unionTraversals, 0, traversalIndex);
- unionTraversals = temp;
- }
- return unionTraversals;
- }
- /**
- * @throws NoEdgeRuleFoundException
- * @throws AAIException
- * @{inheritDoc}
- */
- @Override
- public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
- String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- Introspector parentObj = loader.introspectorFromName(nodeType);
- this.edgeQueryToVertex(type, parentObj, child);
- return (QueryBuilder<Vertex>) this;
-
+ return unionTraversals.toArray(new Traversal[unionTraversals.size()]);
}
-
- @Override
- public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
+
+ public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
Introspector outObj = loader.introspectorFromName(outNodeType);
Introspector inObj = loader.introspectorFromName(inNodeType);
- this.edgeQuery(type, outObj, inObj);
-
- return (QueryBuilder<Edge>)this;
+ this.edgeQuery(type, outObj, inObj, labels);
+ return (QueryBuilder<Edge>)this;
}
+
+
/**
* @{inheritDoc}
*/
@@ -477,12 +480,12 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
/**
* Edge query.
*
- * @param outType the out type
- * @param inType the in type
+ * @param outObj the out type
+ * @param inObj the in type
* @throws NoEdgeRuleFoundException
* @throws AAIException
*/
- private void edgeQueryToVertex(EdgeType type, Introspector outObj, Introspector inObj) throws AAIException, NoEdgeRuleFoundException {
+ private void edgeQueryToVertex(EdgeType type, Introspector outObj, Introspector inObj, List<String> labels) throws AAIException {
String outType = outObj.getDbName();
String inType = inObj.getDbName();
@@ -493,13 +496,38 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
inType = inObj.getChildDBName();
}
markParentBoundary();
- EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
- if (rule.getDirection().equals(Direction.OUT)) {
- traversal.out(rule.getLabel());
+ Map<String, EdgeRule> rules;
+ if (labels == null) {
+ rules = edgeRules.getEdgeRules(type, outType, inType);
} else {
- traversal.in(rule.getLabel());
+ rules = edgeRules.getEdgeRulesWithLabels(type, outType, inType, labels);
+ }
+
+ final List<String> inLabels = new ArrayList<>();
+ final List<String> outLabels = new ArrayList<>();
+
+ rules.forEach((k, edgeRule) -> {
+ if (labels != null && !labels.contains(k)) {
+ return;
+ } else {
+ if (edgeRule.getDirection().equals(Direction.IN)) {
+ inLabels.add(edgeRule.getLabel());
+ } else {
+ outLabels.add(edgeRule.getLabel());
+ }
+ }
+ });
+
+ if (inLabels.isEmpty() && !outLabels.isEmpty()) {
+ traversal.out(outLabels.toArray(new String[outLabels.size()]));
+ } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
+ traversal.in(inLabels.toArray(new String[inLabels.size()]));
+ } else {
+ traversal.union(__.out(outLabels.toArray(new String[outLabels.size()])), __.in(inLabels.toArray(new String[inLabels.size()])));
}
+
stepIndex++;
+
this.createContainerQuery(inObj);
}
@@ -507,12 +535,12 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
/**
* Edge query.
*
- * @param outType the out type
- * @param inType the in type
+ * @param outObj the out type
+ * @param inObj the in type
* @throws NoEdgeRuleFoundException
* @throws AAIException
*/
- private void edgeQuery(EdgeType type, Introspector outObj, Introspector inObj) throws AAIException, NoEdgeRuleFoundException {
+ private void edgeQuery(EdgeType type, Introspector outObj, Introspector inObj, List<String> labels) throws AAIException {
String outType = outObj.getDbName();
String inType = inObj.getDbName();
@@ -522,15 +550,37 @@ public abstract class GraphTraversalBuilder<E> extends QueryBuilder<E> {
if (inObj.isContainer()) {
inType = inObj.getChildDBName();
}
+
markParentBoundary();
- EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
- if (rule.getDirection().equals(Direction.OUT)) {
- traversal.outE(rule.getLabel());
+ Map<String, EdgeRule> rules;
+ if (labels == null) {
+ rules = edgeRules.getEdgeRules(type, outType, inType);
} else {
- traversal.inE(rule.getLabel());
+ rules = edgeRules.getEdgeRulesWithLabels(type, outType, inType, labels);
}
- stepIndex++;
+ final List<String> inLabels = new ArrayList<>();
+ final List<String> outLabels = new ArrayList<>();
+
+ rules.forEach((k, edgeRule) -> {
+ if (labels != null && !labels.contains(k)) {
+ return;
+ } else {
+ if (edgeRule.getDirection().equals(Direction.IN)) {
+ inLabels.add(edgeRule.getLabel());
+ } else {
+ outLabels.add(edgeRule.getLabel());
+ }
+ }
+ });
+
+ if (inLabels.isEmpty() && !outLabels.isEmpty()) {
+ traversal.outE(outLabels.toArray(new String[outLabels.size()]));
+ } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
+ traversal.inE(inLabels.toArray(new String[inLabels.size()]));
+ } else {
+ traversal.union(__.outE(outLabels.toArray(new String[outLabels.size()])), __.inE(inLabels.toArray(new String[inLabels.size()])));
+ }
}
@Override
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java
index 62ba5392..f2eaa91f 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinQueryBuilder.java
@@ -23,7 +23,6 @@ package org.onap.aai.query.builder;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -67,7 +66,19 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
*/
public GremlinQueryBuilder(Loader loader, GraphTraversalSource source) {
super(loader, source);
- list = new ArrayList<String>();
+ list = new ArrayList<>();
+ }
+
+ /**
+ * Instantiates a new graph gremlin builder.
+ *
+ * @param loader the loader
+ */
+ public GremlinQueryBuilder(Loader loader, GraphTraversalSource source, EdgeRules edgeRules) {
+ super(loader, source);
+ this.edgeRules = edgeRules;
+ list = new ArrayList<>();
+
}
/**
@@ -78,43 +89,29 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
*/
public GremlinQueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
super(loader, source, start);
- list = new ArrayList<String>();
+ list = new ArrayList<>();
}
/**
- * @{inheritDoc}
+ * Instantiates a new graph gremlin builder.
+ *
+ * @param loader the loader
+ * @param start the start
*/
- @Override
- public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
- this.createKeyQuery(obj);
- this.createContainerQuery(obj);
- return (QueryBuilder<Vertex>) this;
+ public GremlinQueryBuilder(Loader loader, GraphTraversalSource source, Vertex start, EdgeRules edgeRules) {
+ super(loader, source, start);
+ this.edgeRules = edgeRules;
+ list = new ArrayList<>();
+
}
@Override
public QueryBuilder<Vertex> exactMatchQuery(Introspector obj) {
// TODO not implemented because this is implementation is no longer used
this.createKeyQuery(obj);
- //allPropertiesQuery(obj);
this.createContainerQuery(obj);
return (QueryBuilder<Vertex>) this;
}
-
- /**
- * @{inheritDoc}
- */
- @Override
- public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
- return this.getVerticesByProperty(key, value);
- }
-
- /**
- * @{inheritDoc}
- */
- @Override
- public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
- return this.getVerticesByProperty(key, values);
- }
/**
* @{inheritDoc}
@@ -123,7 +120,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) {
String term = "";
- if (value != null && !value.getClass().getName().equals("java.lang.String")) {
+ if (value != null && !(value instanceof String) ) {
term = value.toString();
} else {
term = "'" + value + "'";
@@ -143,7 +140,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
String predicate = "P.within(#!#argument#!#)";
List<String> arguments = new ArrayList<>();
for (Object item : values) {
- if (item != null && !item.getClass().getName().equals("java.lang.String")) {
+ if (item != null && !(item instanceof String)) {
arguments.add(item.toString());
} else {
arguments.add("'" + item + "'");
@@ -175,10 +172,10 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
* @{inheritDoc}
*/
@Override
- public QueryBuilder<Vertex> getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
+ public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) {
- for (String key : map.keySet()) {
- list.add(".has('" + key + "', '" + map.get(key) + "')");
+ for (Map.Entry<String, String> es : map.entrySet()) {
+ list.add(".has('" + es.getKey() + "', '" + es.getValue() + "')");
stepIndex++;
}
list.add(".has('aai-node-type', '" + type + "')");
@@ -207,7 +204,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
* @{inheritDoc}
*/
@Override
- public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
+ public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException {
String parentName = parent.getDbName();
String childName = child.getDbName();
if (parent.isContainer()) {
@@ -216,47 +213,73 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
if (child.isContainer()) {
childName = child.getChildDBName();
}
- this.edgeQueryToVertex(type, parentName, childName);
+ this.edgeQueryToVertex(type, parentName, childName, null);
return this;
}
-
+
/**
- * @throws NoEdgeRuleFoundException
- * @throws AAIException
+ *
* @{inheritDoc}
*/
@Override
- public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
- String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- this.edgeQueryToVertex(type, nodeType, child.getDbName());
-
+ public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException {
+ String parentName = out.getDbName();
+ String childName = in.getDbName();
+ if (out.isContainer()) {
+ parentName = out.getChildDBName();
+ }
+ if (in.isContainer()) {
+ childName = in.getChildDBName();
+ }
+ this.edgeQueryToVertex(type, parentName, childName, labels);
return (QueryBuilder<Vertex>) this;
-
}
-
- @Override
- public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
- this.edgeQuery(type, outNodeType, inNodeType);
-
- return (QueryBuilder<Edge>)this;
+
+ public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
+ this.edgeQuery(type, outNodeType, inNodeType, labels);
+ return (QueryBuilder<Edge>)this;
}
+
/**
* Edge query.
*
* @param outType the out type
* @param inType the in type
- * @throws NoEdgeRuleFoundException
- * @throws AAIException
+ * @throws NoEdgeRuleFoundException
+ * @throws AAIException
*/
- private void edgeQueryToVertex(EdgeType type, String outType, String inType) throws AAIException, NoEdgeRuleFoundException {
+ private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
markParentBoundary();
- EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
- if (rule.getDirection().equals(Direction.OUT)) {
- list.add(".out('" + rule.getLabel() + "')");
+ Map<String, EdgeRule> rules;
+ if (labels == null) {
+ rules = edgeRules.getEdgeRules(type, outType, inType);
} else {
- list.add(".in('" + rule.getLabel() + "')");
+ rules = edgeRules.getEdgeRulesWithLabels(type, outType, inType, labels);
+ }
+
+ final List<String> inLabels = new ArrayList<>();
+ final List<String> outLabels = new ArrayList<>();
+
+ rules.forEach((k, edgeRule) -> {
+ if (labels != null && !labels.contains(k)) {
+ return;
+ } else {
+ if (edgeRule.getDirection().equals(Direction.IN)) {
+ inLabels.add(edgeRule.getLabel());
+ } else {
+ outLabels.add(edgeRule.getLabel());
+ }
+ }
+ });
+
+ if (inLabels.isEmpty() && !outLabels.isEmpty()) {
+ list.add(".out('" + String.join("','", outLabels) + "')");
+ } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
+ list.add(".in('" + String.join("','", inLabels) + "')");
+ } else {
+ list.add(".union(__.in('" + String.join("','", inLabels) + "')" + ", __.out('" + String.join("','", outLabels) + "'))");
}
stepIndex++;
list.add(".has('" + AAIProperties.NODE_TYPE + "', '" + inType + "')");
@@ -272,14 +295,38 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
* @throws NoEdgeRuleFoundException
* @throws AAIException
*/
- private void edgeQuery(EdgeType type, String outType, String inType) throws AAIException, NoEdgeRuleFoundException {
+ private void edgeQuery(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
markParentBoundary();
- EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
- if (rule.getDirection().equals(Direction.OUT)) {
- list.add(".outE('" + rule.getLabel() + "')");
+ Map<String, EdgeRule> rules;
+ if (labels == null) {
+ rules = edgeRules.getEdgeRules(type, outType, inType);
} else {
- list.add(".inV('" + rule.getLabel() + "')");
+ rules = edgeRules.getEdgeRulesWithLabels(type, outType, inType, labels);
}
+
+ final List<String> inLabels = new ArrayList<>();
+ final List<String> outLabels = new ArrayList<>();
+
+ rules.forEach((k, edgeRule) -> {
+ if (labels != null && !labels.contains(k)) {
+ return;
+ } else {
+ if (edgeRule.getDirection().equals(Direction.IN)) {
+ inLabels.add(edgeRule.getLabel());
+ } else {
+ outLabels.add(edgeRule.getLabel());
+ }
+ }
+ });
+
+ if (inLabels.isEmpty() && !outLabels.isEmpty()) {
+ list.add(".outE('" + String.join("','", outLabels) + "')");
+ } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
+ list.add(".inE('" + String.join("','", inLabels) + "')");
+ } else {
+ list.add(".union(__.inE('" + String.join("','", inLabels) + "')" + ", __.outE('" + String.join("','", outLabels) + "'))");
+ }
+
stepIndex++;
}
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java
index 801ac339..b3d3f755 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinTraversal.java
@@ -35,6 +35,7 @@ import org.onap.aai.introspection.Introspector;
import org.onap.aai.introspection.Loader;
import org.onap.aai.parsers.query.QueryParser;
import org.onap.aai.parsers.query.TraversalStrategy;
+import org.onap.aai.serialization.db.EdgeRules;
/**
* The Class GremlinTraversal.
@@ -46,6 +47,16 @@ public class GremlinTraversal<E> extends GremlinQueryBuilder<E> {
*
* @param loader the loader
*/
+ public GremlinTraversal(Loader loader, GraphTraversalSource source, EdgeRules ers) {
+ super(loader, source, ers);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ /**
+ * Instantiates a new gremlin traversal.
+ *
+ * @param loader the loader
+ */
public GremlinTraversal(Loader loader, GraphTraversalSource source) {
super(loader, source);
this.factory = new TraversalStrategy(this.loader, this);
@@ -61,6 +72,17 @@ public class GremlinTraversal<E> extends GremlinQueryBuilder<E> {
super(loader, source, start);
this.factory = new TraversalStrategy(this.loader, this);
}
+
+ /**
+ * Instantiates a new gremlin traversal.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public GremlinTraversal(Loader loader, GraphTraversalSource source, Vertex start, EdgeRules ers) {
+ super(loader, source, start, ers);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
protected GremlinTraversal(List<String> traversal, Loader loader, GraphTraversalSource source, GremlinQueryBuilder<E> gtb) {
super(loader, source);
@@ -124,11 +146,15 @@ public class GremlinTraversal<E> extends GremlinQueryBuilder<E> {
@Override
protected QueryBuilder<E> cloneQueryAtStep(int index) {
- if (index == 0) {
- index = stepIndex;
+
+ int idx = index;
+
+ if (idx == 0) {
+ idx = stepIndex;
}
+
List<String> newList = new ArrayList<>();
- for (int i = 0; i < index; i++) {
+ for (int i = 0; i < idx; i++) {
newList.add(this.list.get(i));
}
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java
index 284f8847..85bd7ab4 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/GremlinUnique.java
@@ -125,11 +125,15 @@ public class GremlinUnique<E> extends GremlinQueryBuilder<E> {
@Override
protected QueryBuilder<E> cloneQueryAtStep(int index) {
- if (index == 0) {
- index = stepIndex;
+
+ int idx = index;
+
+ if (idx == 0) {
+ idx = stepIndex;
}
+
List<String> newList = new ArrayList<>();
- for (int i = 0; i < index; i++) {
+ for (int i = 0; i < idx; i++) {
newList.add(this.list.get(i));
}
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java
index 3a3feafb..5f91a44f 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java
@@ -24,35 +24,32 @@ package org.onap.aai.query.builder;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.Introspector;
import org.onap.aai.introspection.Loader;
import org.onap.aai.parsers.query.QueryParser;
import org.onap.aai.parsers.query.QueryParserStrategy;
import org.onap.aai.serialization.db.EdgeType;
-import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
/**
* The Class QueryBuilder.
*/
public abstract class QueryBuilder<E> implements Iterator<E> {
+ protected final GraphTraversalSource source;
protected QueryParserStrategy factory = null;
-
protected Loader loader = null;
-
protected boolean optimize = false;
-
protected Vertex start = null;
- protected final GraphTraversalSource source;
/**
* Instantiates a new query builder.
@@ -83,7 +80,9 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
* @param value the value
* @return the vertices by indexed property
*/
- public abstract QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value);
+ public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
+ return this.getVerticesByProperty(key, value);
+ }
/**
* Gets the vertices by property.
@@ -100,7 +99,9 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
* @param values
* @return vertices that match these values
*/
- public abstract QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values);
+ public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
+ return this.getVerticesByProperty(key, values);
+ }
/**
* filters by all the values for this property
@@ -127,7 +128,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
* @param map the map
* @return the typed vertices by map
*/
- public abstract QueryBuilder<Vertex> getTypedVerticesByMap(String type, LinkedHashMap<String, String> map);
+ public abstract QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map);
/**
* Creates the DB query.
@@ -135,7 +136,11 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
* @param obj the obj
* @return the query builder
*/
- public abstract QueryBuilder<Vertex> createDBQuery(Introspector obj);
+ public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
+ this.createKeyQuery(obj);
+ this.createContainerQuery(obj);
+ return (QueryBuilder<Vertex>) this;
+ }
/**
* Creates the key query.
@@ -169,16 +174,79 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
* @param child the child
* @return the query builder
*/
- public abstract QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException;
+ public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException {
+ String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ this.createEdgeTraversal(type, nodeType, child.getDbName());
+ return (QueryBuilder<Vertex>) this;
+
+ }
- public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws NoEdgeRuleFoundException, AAIException {
+ /**
+ *
+ * @param type
+ * @param outNodeType
+ * @param inNodeType
+ * @return
+ * @throws AAIException
+ */
+ public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
Introspector out = loader.introspectorFromName(outNodeType);
Introspector in = loader.introspectorFromName(inNodeType);
-
+
return createEdgeTraversal(type, out, in);
}
-
- public abstract QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException;
+
+ /**
+ *
+ * @param type
+ * @param outNodeType
+ * @param inNodeType
+ * @param labels
+ * @return
+ * @throws AAIException
+ */
+ public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
+ Introspector out = loader.introspectorFromName(outNodeType);
+ Introspector in = loader.introspectorFromName(inNodeType);
+
+ return createEdgeTraversalWithLabels(type, out, in, labels);
+ }
+
+ /**
+ *
+ * @param type
+ * @param out
+ * @param in
+ * @param labels
+ * @return
+ */
+ public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
+
+ /**
+ *
+ * @param type
+ * @param outNodeType
+ * @param inNodeType
+ * @return
+ * @throws AAIException
+ */
+ public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
+ this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
+
+ return (QueryBuilder<Edge>)this;
+
+ }
+ /**
+ *
+ * @param type
+ * @param outNodeType
+ * @param inNodeType
+ * @param labels
+ * @return
+ * @throws AAIException
+ */
+ public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
+
/**
* Creates the query from URI.
*
@@ -238,6 +306,7 @@ public abstract class QueryBuilder<E> implements Iterator<E> {
public abstract void markParentBoundary();
public abstract QueryBuilder<E> limit(long amount);
+
/**
* New instance.
*
diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java
index 60e72aa5..014ce79d 100644
--- a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java
+++ b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java
@@ -31,12 +31,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Vertex;
-
import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.Introspector;
import org.onap.aai.introspection.Loader;
import org.onap.aai.parsers.query.QueryParser;
import org.onap.aai.parsers.query.TraversalStrategy;
+import org.onap.aai.serialization.db.EdgeRules;
/**
* The Class TraversalQuery.
@@ -57,6 +57,19 @@ public class TraversalQuery<E> extends GraphTraversalBuilder<E> {
* Instantiates a new traversal query.
*
* @param loader the loader
+ * @param source graph traversal source
+ * @param edgeRules the edgeRules to use
+ */
+ public TraversalQuery(Loader loader, GraphTraversalSource source, EdgeRules edgeRules) {
+ super(loader, source, edgeRules);
+ this.factory = new TraversalStrategy(this.loader, this);
+
+ }
+
+ /**
+ * Instantiates a new traversal query.
+ *
+ * @param loader the loader
* @param start the start
*/
public TraversalQuery(Loader loader, GraphTraversalSource source, Vertex start) {
@@ -64,6 +77,17 @@ public class TraversalQuery<E> extends GraphTraversalBuilder<E> {
this.factory = new TraversalStrategy(this.loader, this);
}
+ /**
+ * Instantiates a new traversal query.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public TraversalQuery(Loader loader, GraphTraversalSource source, Vertex start, EdgeRules edgeRules) {
+ super(loader, source, start, edgeRules);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
protected TraversalQuery(GraphTraversal<Vertex, E> traversal, Loader loader, GraphTraversalSource source, GraphTraversalBuilder<E> gtb) {
super(loader, source);
this.traversal = traversal;
@@ -125,14 +149,17 @@ public class TraversalQuery<E> extends GraphTraversalBuilder<E> {
@Override
protected QueryBuilder<E> cloneQueryAtStep(int index) {
- if (index == 0) {
- index = stepIndex;
+ int idx = index;
+
+ if (idx == 0) {
+ idx = stepIndex;
}
+
GraphTraversal<Vertex, E> clone = this.traversal.asAdmin().clone();
GraphTraversal.Admin<Vertex, E> cloneAdmin = clone.asAdmin();
List<Step> steps = cloneAdmin.getSteps();
- for (int i = steps.size()-1; i >= index; i--) {
+ for (int i = steps.size()-1; i >= idx; i--) {
cloneAdmin.removeStep(i);
}
return new TraversalQuery<>(cloneAdmin, loader, source, this);
diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
index 634e44e9..0d89a74c 100644
--- a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
+++ b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
@@ -461,14 +461,13 @@ public class HttpEntry {
private Introspector getObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIUnknownObjectException, URISyntaxException {
//nothing found
- if (results.size() == 0) {
+ if (results.isEmpty()) {
String msg = createNotFoundMessage(query.getResultType(), uri);
throw new AAIException("AAI_6114", msg);
}
- obj = serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
+ return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
- return obj;
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java
index dd073dc7..cd48fc6a 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java
@@ -1,40 +1,67 @@
-/**
+/*-
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 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
- *
+ *
+ * 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
+
package org.onap.aai.serialization.db;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-import com.google.common.base.CaseFormat;
-import com.thinkaurelius.titan.core.SchemaViolationException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.core.UriBuilder;
+
import org.apache.commons.collections.IteratorUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
-import org.apache.tinkerpop.gremlin.structure.*;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.javatuples.Pair;
+import org.javatuples.Triplet;
import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.exceptions.AAIException;
-import org.onap.aai.introspection.*;
+import org.onap.aai.introspection.Introspector;
+import org.onap.aai.introspection.IntrospectorFactory;
+import org.onap.aai.introspection.Loader;
+import org.onap.aai.introspection.LoaderFactory;
+import org.onap.aai.introspection.ModelType;
+import org.onap.aai.introspection.PropertyPredicates;
+import org.onap.aai.introspection.Version;
import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
import org.onap.aai.introspection.sideeffect.DataCopy;
import org.onap.aai.introspection.sideeffect.DataLinkReader;
@@ -48,6 +75,7 @@ import org.onap.aai.query.builder.QueryBuilder;
import org.onap.aai.schema.enums.ObjectMetadata;
import org.onap.aai.schema.enums.PropertyMetadata;
import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
+import org.onap.aai.serialization.db.util.VersionChecker;
import org.onap.aai.serialization.engines.TransactionalGraphEngine;
import org.onap.aai.serialization.tinkerpop.TreeBackedVertex;
import org.onap.aai.util.AAIApiServerURLBase;
@@ -55,18 +83,10 @@ import org.onap.aai.util.AAIConfig;
import org.onap.aai.util.AAIConstants;
import org.onap.aai.workarounds.NamingExceptions;
-import javax.ws.rs.core.UriBuilder;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.*;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.base.CaseFormat;
+import com.thinkaurelius.titan.core.SchemaViolationException;
public class DBSerializer {
@@ -109,8 +129,7 @@ public class DBSerializer {
*/
public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) {
- long unixTimeNow = System.currentTimeMillis();
- String timeNowInSec = "" + unixTimeNow;
+ String timeNowInSec = Long.toString(System.currentTimeMillis());
if (isNewVertex) {
v.property(AAIProperties.SOURCE_OF_TRUTH, this.sourceOfTruth);
v.property(AAIProperties.CREATED_TS, timeNowInSec);
@@ -391,15 +410,20 @@ public class DBSerializer {
List<Object> relationships = (List<Object>)wrapped.getValue("relationship");
- List<Pair<Vertex, Vertex>> addEdges = new ArrayList<>();
+ List<Triplet<Vertex, Vertex, String>> addEdges = new ArrayList<>();
List<Edge> existingEdges = this.engine.getQueryEngine().findEdgesForVersion(v, wrapped.getLoader());
for (Object relationship : relationships) {
Edge e = null;
Vertex cousinVertex = null;
+ String label = null;
Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship);
QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel);
+ if (wrappedRel.hasProperty("relationship-label")) {
+ label = wrappedRel.getValue("relationship-label");
+ }
+
List<Vertex> results = parser.getQueryBuilder().toList();
if (results.isEmpty()) {
final AAIException ex = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
@@ -412,30 +436,30 @@ public class DBSerializer {
}
if (cousinVertex != null) {
- try {
- if (!edgeRules.hasEdgeRule(v, cousinVertex)) {
- throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + v.property(AAIProperties.NODE_TYPE).value().toString() + ", "
- + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() + ".");
- }
- e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex);
-
- if (e == null) {
- addEdges.add(new Pair<>(v, cousinVertex));
- } else {
- existingEdges.remove(e);
- }
- } catch (NoEdgeRuleFoundException e1) {
+
+ if (!edgeRules.hasEdgeRule(v, cousinVertex, label)) {
+ throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + v.property(AAIProperties.NODE_TYPE).value().toString() + ", "
+ + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() + (label != null ? (" with label " + label):"") +".");
+ } else if (edgeRules.hasTreeEdgeRule(v, cousinVertex) && !edgeRules.hasCousinEdgeRule(v, cousinVertex, label)) {
throw new AAIException("AAI_6145");
}
+
+ e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex, label);
+
+ if (e == null) {
+ addEdges.add(new Triplet<>(v, cousinVertex, label));
+ } else {
+ existingEdges.remove(e);
+ }
}
}
for (Edge edge : existingEdges) {
edge.remove();
}
- for (Pair<Vertex, Vertex> pair : addEdges) {
+ for (Triplet<Vertex, Vertex, String> triplet : addEdges) {
try {
- edgeRules.addEdge(this.engine.asAdmin().getTraversalSource(), pair.getValue0(), pair.getValue1());
+ edgeRules.addEdge(this.engine.asAdmin().getTraversalSource(), triplet.getValue0(), triplet.getValue1(), triplet.getValue2());
} catch (NoEdgeRuleFoundException e) {
throw new AAIException("AAI_6129", e);
}
@@ -491,7 +515,7 @@ public class DBSerializer {
//QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI());
//List<Vertex> items = p.getQuery().toList();
- QueryBuilder query = this.engine.getQueryBuilder(v);
+ QueryBuilder<Vertex> query = this.engine.getQueryBuilder(v);
query.createEdgeTraversal(EdgeType.TREE, v, dependentObj);
query.createKeyQuery(dependentObj);
@@ -531,14 +555,13 @@ public class DBSerializer {
String parentUri = parent.<String>property(AAIProperties.AAI_URI).orElse(null);
if (parentUri != null) {
- String uri;
- uri = obj.getURI();
+ String uri = obj.getURI();
child.property(AAIProperties.AAI_URI, parentUri + uri);
}
processObject(obj, child, requestContext);
Edge e;
- e = this.getEdgeBetween(EdgeType.TREE, parent, child);
+ e = this.getEdgeBetween(EdgeType.TREE, parent, child, null);
if (e == null) {
String canBeLinked = obj.getMetadata(ObjectMetadata.CAN_BE_LINKED);
if (canBeLinked != null && canBeLinked.equals("true")) {
@@ -617,9 +640,7 @@ public class DBSerializer {
for (Future<Object> future : futures) {
try {
getList.add(future.get());
- } catch (ExecutionException e) {
- throw new AAIException("AAI_4000", e);
- } catch (InterruptedException e) {
+ } catch (ExecutionException | InterruptedException e) {
throw new AAIException("AAI_4000", e);
}
}
@@ -726,7 +747,7 @@ public class DBSerializer {
Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
Object result = dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp);
- if (result != null && getList != null) {
+ if (result != null) {
getList.add(argumentObject.getUnderlyingObject());
}
@@ -868,19 +889,28 @@ public class DBSerializer {
*/
private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp) throws UnsupportedEncodingException, AAIException {
-
List<Vertex> cousins = this.engine.getQueryEngine().findCousinVertices(v);
List<Object> relationshipObjList = obj.getValue("relationship");
for (Vertex cousin : cousins) {
-
+ if (VersionChecker.apiVersionNeedsEdgeLabel(obj.getVersion())) {
+ List<Edge> edges = this.getEdgesBetween(EdgeType.COUSIN, v, cousin);
+ for (Edge e : edges) {
+ Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, e);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+ } else {
Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
- Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp);
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
if (result != null) {
relationshipObjList.add(result);
}
-
+ }
+
}
if (relationshipObjList.isEmpty()) {
@@ -910,7 +940,7 @@ public class DBSerializer {
* @throws AAIUnknownObjectException
* @throws URISyntaxException
*/
- private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp) throws UnsupportedEncodingException, AAIUnknownObjectException {
+ private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp, Edge edge) throws UnsupportedEncodingException, AAIUnknownObjectException {
//we must look up all parents in this case because we need to compute name-properties
@@ -935,11 +965,14 @@ public class DBSerializer {
}
return null;
}
-
- if(list.size() > 0 && this.version.compareTo(Version.v8) >= 0){
+ if (!list.isEmpty()) {
this.addRelatedToProperty(result, list.get(0));
}
-
+
+ if (edge != null && result.hasProperty("relationship-label")) {
+ result.setValue("relationship-label", edge.label());
+ }
+
return result.getUnderlyingObject();
}
@@ -993,8 +1026,7 @@ public class DBSerializer {
}
uri = sb.toString();
- URI result = UriBuilder.fromPath(uri).build();
- return result;
+ return UriBuilder.fromPath(uri).build();
}
/**
@@ -1063,19 +1095,19 @@ public class DBSerializer {
*/
public void setCachedURIs(List<Vertex> vertices, List<Introspector> objs) throws UnsupportedEncodingException, URISyntaxException {
- String uriChain = "";
+ StringBuilder uriChain = new StringBuilder();
for (int i = 0; i < vertices.size(); i++) {
String aaiUri = "";
Vertex v = null;
v = vertices.get(i);
aaiUri = v.<String>property(AAIProperties.AAI_URI).orElse(null);
if (aaiUri != null) {
- uriChain += aaiUri;
+ uriChain.append(aaiUri);
} else {
URI uri = UriBuilder.fromPath(objs.get(i).getURI()).build();
aaiUri = uri.toString();
- uriChain += aaiUri;
- v.property(AAIProperties.AAI_URI, uriChain);
+ uriChain.append(aaiUri);
+ v.property(AAIProperties.AAI_URI, uriChain.toString());
}
}
@@ -1106,7 +1138,7 @@ public class DBSerializer {
}
}
- if (relatedToProperties.size() > 0) {
+ if (!relatedToProperties.isEmpty()) {
List relatedToList = (List)relationship.getValue("related-to-property");
for (Introspector obj : relatedToProperties) {
relatedToList.add(obj.getUnderlyingObject());
@@ -1130,8 +1162,13 @@ public class DBSerializer {
QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
+ String label = null;
+ if (relationship.hasProperty("relationship-label")) {
+ label = relationship.getValue("relationship-label");
+ }
+
List<Vertex> results = parser.getQueryBuilder().toList();
- if (results.size() == 0) {
+ if (results.isEmpty()) {
AAIException e = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
e.getTemplateVars().add(parser.getResultType());
e.getTemplateVars().add(parser.getUri().toString());
@@ -1143,29 +1180,19 @@ public class DBSerializer {
if (relatedVertex != null) {
- Edge e;
- try {
- e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex);
- if (e == null) {
- edgeRules.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex);
-
- } else {
- //attempted to link two vertexes already linked
- }
- } catch (NoEdgeRuleFoundException e1) {
- throw new AAIException("AAI_6129", e1);
+ Edge e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
+ if (e == null) {
+ edgeRules.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label);
+ } else {
+ //attempted to link two vertexes already linked
}
-
-
-
-
}
return true;
}
/**
- * Gets the edges between.
+ * Gets all the edges between of the type.
*
* @param aVertex the out vertex
* @param bVertex the in vertex
@@ -1173,44 +1200,67 @@ public class DBSerializer {
* @throws AAIException the AAI exception
* @throws NoEdgeRuleFoundException
*/
- private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException, NoEdgeRuleFoundException {
+ private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
List<Edge> result = new ArrayList<>();
if (bVertex != null) {
- EdgeRule rule = edgeRules.getEdgeRule(type, aVertex, bVertex);
- GraphTraversal<Vertex, Edge> findEdgesBetween = null;
- findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE(rule.getLabel()).filter(__.otherV().hasId(bVertex.id()));
- List<Edge> edges = findEdgesBetween.toList();
- for (Edge edge : edges) {
- if (edge.label().equals(rule.getLabel())) {
- result.add(edge);
- }
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
+ if (EdgeType.TREE.equals(type)) {
+ findEdgesBetween = findEdgesBetween.not(__.has(EdgeProperty.CONTAINS.toString(), "NONE"));
+ } else {
+ findEdgesBetween = findEdgesBetween.has(EdgeProperty.CONTAINS.toString(), "NONE");
+ }
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
+ result = findEdgesBetween.toList();
+ }
+
+ return result;
+ }
+ /**
+ * Gets all the edges between the vertexes with the label and type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @param label
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ */
+ private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+
+ List<Edge> result = new ArrayList<>();
+
+ if (bVertex != null) {
+ EdgeRule rule = edgeRules.getEdgeRule(type, aVertex, bVertex, label);
+ List<Edge> edges = this.getEdgesBetween(type, aVertex, bVertex);
+ for (Edge edge : edges) {
+ if (edge.label().equals(rule.getLabel())) {
+ result.add(edge);
}
-
+ }
}
return result;
}
/**
- * Gets the edge between.
+ * Gets the edge between with the label and edge type.
*
* @param aVertex the out vertex
* @param bVertex the in vertex
+ * @param label
* @return the edge between
* @throws AAIException the AAI exception
* @throws NoEdgeRuleFoundException
*/
- public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
-
-
-
+ public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+
if (bVertex != null) {
- List<Edge> edges = this.getEdgesBetween(type, aVertex, bVertex);
+ List<Edge> edges = this.getEdgesBetween(type, aVertex, bVertex, label);
- if (edges.size() > 0) {
+ if (!edges.isEmpty()) {
return edges.get(0);
}
@@ -1218,6 +1268,9 @@ public class DBSerializer {
return null;
}
+ public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
+ return this.getEdgeBetween(type, aVertex, bVertex, null);
+ }
/**
@@ -1236,15 +1289,20 @@ public class DBSerializer {
QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
List<Vertex> results = parser.getQueryBuilder().toList();
+
+ String label = null;
+ if (relationship.hasProperty("relationship-label")) {
+ label = relationship.getValue("relationship-label");
+ }
- if (results.size() == 0) {
+ if (results.isEmpty()) {
return false;
}
relatedVertex = results.get(0);
Edge edge;
try {
- edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex);
+ edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
} catch (NoEdgeRuleFoundException e) {
throw new AAIException("AAI_6129", e);
}
@@ -1329,7 +1387,7 @@ public class DBSerializer {
}
List<Object> preventDeleteVertices = this.engine.asAdmin().getReadOnlyTraversalSource().V(vertex).union(__.inE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.IN.toString()).outV().values(AAIProperties.NODE_TYPE), __.outE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.OUT.toString()).inV().values(AAIProperties.NODE_TYPE)).dedup().toList();
- if (preventDeleteVertices.size() > 0) {
+ if (!preventDeleteVertices.isEmpty()) {
aaiExceptionCode = "AAI_6110";
errorDetail = String.format("Object is being reference by additional objects preventing it from being deleted. Please clean up references from the following types %s", preventDeleteVertices);
result = false;
@@ -1368,7 +1426,7 @@ public class DBSerializer {
ErrorLogHelper.logException(e);
}
// We're only doing the resource version checks for v5 and later
- if (enabled.equals("true") && this.version.compareTo(Version.v8) > 0) {
+ if (enabled.equals("true")) {
if (!currentResourceVersion.equals(resourceVersion)) {
if (action.equals("create") && !resourceVersion.equals("")) {
errorDetail = "resource-version passed for " + action + " of " + uri;
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeProperty.java b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeProperty.java
index 29d82298..ecd749c7 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeProperty.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeProperty.java
@@ -1,37 +1,30 @@
-/**
+/*-
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 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
- *
+ *
+ * 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
+
package org.onap.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/onap/aai/serialization/db/EdgeRule.java b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRule.java
index 309dbffe..ae9e96c0 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRule.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRule.java
@@ -1,43 +1,43 @@
-/**
+/*-
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 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
- *
+ *
+ * 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.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
-package org.onap.aai.serialization.db;
-import org.apache.tinkerpop.gremlin.structure.Direction;
+package org.onap.aai.serialization.db;
-import java.util.HashMap;
+import java.util.EnumMap;
import java.util.Map;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+
public class EdgeRule {
private String label = "";
private MultiplicityRule multiplicityRule = null;
private Direction direction = null;
private Map<EdgeProperty, String> edgeProperties = null;
+ private boolean isDefaultEdge = false;
/**
* Instantiates a new edge rule.
*/
public EdgeRule() {
- edgeProperties = new HashMap<>();
+ edgeProperties = new EnumMap<>(EdgeProperty.class);
}
/**
@@ -206,6 +206,18 @@ public class EdgeRule {
private String getProp(EdgeProperty key) {
return this.edgeProperties.get(key);
}
+
+ public boolean isDefault() {
+ return isDefaultEdge;
+ }
+
+ public void setIsDefault(boolean isDefault) {
+ this.isDefaultEdge = isDefault;
+ }
+
+ public void setIsDefault(String isDefault) {
+ this.isDefaultEdge = "true".equals(isDefault);
+ }
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRules.java b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRules.java
index d9dfa457..349f9e6b 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRules.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/EdgeRules.java
@@ -44,6 +44,7 @@ import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.Version;
import org.onap.aai.serialization.db.exceptions.EdgeMultiplicityException;
+import org.onap.aai.serialization.db.exceptions.MultipleEdgeRuleFoundException;
import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
import com.att.eelf.configuration.EELFLogger;
@@ -56,6 +57,12 @@ import com.jayway.jsonpath.JsonPath;
public class EdgeRules {
+ private static final String LABEL = "label";
+
+ private static final String NOT_DIRECTION_NOTATION = "!${direction}";
+
+ private static final String DIRECTION_NOTATION = "${direction}";
+
private EELFLogger logger = EELFManager.getInstance().getLogger(EdgeRules.class);
private DocumentContext rulesDoc;
@@ -77,54 +84,14 @@ public class EdgeRules {
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);
}
-
- private String getEdgeRuleJson(Version version) {
- InputStream is = getClass().getResourceAsStream("/dbedgerules/DbEdgeRules_" + version.toString() + ".json");
- Scanner scanner = new Scanner(is);
- String json = scanner.useDelimiter("\\Z").next();
- scanner.close();
-
- return json;
- }
-
- private static class Helper {
- private static final EdgeRules INSTANCE = new EdgeRules();
- private static final Map<Version, EdgeRules> 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;
- }
- if (!INSTANCEMAP.containsKey(v)) {
- INSTANCEMAP.put(v, new EdgeRules(v));
- }
- return INSTANCEMAP.get(v);
- }
- }
-
/**
* Gets the single instance of EdgeRules.
*
@@ -154,7 +121,21 @@ public class EdgeRules {
public static EdgeRules getInstance(String rulesFilename) {
return Helper.getEdgeRulesByFilename(rulesFilename);
}
+
+ 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;
+ }
+
+ private String getEdgeRuleJson(Version version) {
+ return this.getEdgeRuleJson("/dbedgerules/DbEdgeRules_" + version.toString() + ".json");
+ }
+
/**
* Adds the tree edge.
*
@@ -164,9 +145,9 @@ public class EdgeRules {
* @throws AAIException the AAI exception
*/
public Edge addTreeEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
- return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, false);
+ return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, false, null);
}
-
+
/**
* Adds the edge.
*
@@ -176,9 +157,13 @@ public class EdgeRules {
* @throws AAIException the AAI exception
*/
public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
- return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, false);
+ return this.addEdge(traversalSource, aVertex, bVertex, null);
}
-
+
+ public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+ return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, false, label);
+ }
+
/**
* Adds the tree edge.
*
@@ -188,9 +173,9 @@ public class EdgeRules {
* @throws AAIException the AAI exception
*/
public Edge addTreeEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
- return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, true);
+ return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, true, null);
}
-
+
/**
* Adds the edge.
*
@@ -200,9 +185,13 @@ public class EdgeRules {
* @throws AAIException the AAI exception
*/
public Edge addEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
- return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, true);
+ return this.addEdgeIfPossible(traversalSource, aVertex, bVertex, null);
}
+ public Edge addEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+ return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, true, label);
+ }
+
/**
* Adds the edge.
*
@@ -212,14 +201,14 @@ public class EdgeRules {
* @return the edge
* @throws AAIException the AAI exception
*/
- private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, boolean isBestEffort) throws AAIException {
+ private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, boolean isBestEffort, String label) throws AAIException {
- EdgeRule rule = this.getEdgeRule(type, aVertex, bVertex);
+ EdgeRule rule = this.getEdgeRule(type, aVertex, bVertex, label);
Edge e = null;
-
+
Optional<String> message = this.validateMultiplicity(rule, traversalSource, aVertex, bVertex);
-
+
if (message.isPresent() && !isBestEffort) {
throw new EdgeMultiplicityException(message.get());
}
@@ -229,12 +218,12 @@ public class EdgeRules {
} else if (rule.getDirection().equals(Direction.IN)) {
e = bVertex.addEdge(rule.getLabel(), aVertex);
}
-
+
this.addProperties(e, rule);
}
return e;
}
-
+
/**
* Adds the properties.
*
@@ -242,40 +231,91 @@ public class EdgeRules {
* @param rule the rule
*/
public void addProperties(Edge edge, EdgeRule rule) {
-
+
// In DbEdgeRules.EdgeRules -- What we have as "edgeRule" is a comma-delimited set of strings.
// The first item is the edgeLabel.
// The second in the list is always "direction" which is always OUT for the way we've implemented it.
- // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to
+ // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to
// tags as defined in EdgeInfoMap.
// Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it
Map<EdgeProperty, String> propMap = rule.getEdgeProperties();
-
+
for (Entry<EdgeProperty, String> entry : propMap.entrySet()) {
edge.property(entry.getKey().toString(), entry.getValue());
}
}
-
+
/**
- * Checks if any edge rules exist between the two given nodes, in either A|B or B|A order.
+ * Checks if any edge rules exist between the two given node types, in either A|B or B|A order.
*
* @param nodeA - node at one end of the edge
* @param nodeB - node at the other end
* @return true, if any such rules exist
*/
public boolean hasEdgeRule(String nodeA, String nodeB) {
- Filter aToB = filter(
- where("from").is(nodeA).and("to").is(nodeB)
- );
- Filter bToA = filter(
- where("from").is(nodeB).and("to").is(nodeA)
- );
-
- List<Map<String, String>> results = readRules(aToB);
- results.addAll(readRules(bToA));
+ return this.hasEdgeRule(nodeA, nodeB, null);
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given node types with contains-other-v !NONE, in either A|B or B|A order.
+ *
+ * @param nodeA - node at one end of the edge
+ * @param nodeB - node at the other end
+ * @return true, if any such rules exist
+ */
+ public boolean hasTreeEdgeRule(String nodeA, String nodeB) {
+ return this.hasEdgeRule(EdgeType.TREE, nodeA, nodeB, null);
+ }
- return !results.isEmpty();
-
+ /**
+ * Checks if any edge rules exist between the two given node types with contains-other-v NONE, in either A|B or B|A order.
+ *
+ * @param nodeA - node at one end of the edge
+ * @param nodeB - node at the other end
+ * @param label - edge label
+ * @return true, if any such rules exist
+ */
+ public boolean hasCousinEdgeRule(String nodeA, String nodeB, String label) {
+ return this.hasEdgeRule(EdgeType.COUSIN, nodeA, nodeB, label);
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given nodes with contains-other-v !NONE, in either A|B or B|A order.
+ *
+ * @param aVertex - node at one end of the edge
+ * @param bVertex - node at the other end
+ * @return true, if any such rules exist
+ */
+ public boolean hasTreeEdgeRule(Vertex aVertex, Vertex bVertex) {
+ String outType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String inType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ return this.hasTreeEdgeRule(outType, inType);
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given nodes with contains-other-v NONE with edge label, in either A|B or B|A order.
+ *
+ * @param aVertex - node at one end of the edge
+ * @param bVertex - node at the other end
+ * @param label - edge label
+ * @return true, if any such rules exist
+ */
+ public boolean hasCousinEdgeRule(Vertex aVertex, Vertex bVertex, String label) {
+ String outType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String inType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ return this.hasCousinEdgeRule(outType, inType, label);
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given nodes w/ edge label, in either A|B or B|A order.
+ *
+ * @param nodeA - node at one end of the edge
+ * @param nodeB - node at the other end
+ * @param label - edge label
+ * @return true, if any such rules exist
+ */
+ public boolean hasEdgeRule(String nodeA, String nodeB, String label) {
+ return this.hasEdgeRule(null, nodeA, nodeB, label);
}
/**
@@ -286,11 +326,65 @@ public class EdgeRules {
* @return true, if any such rules exist
*/
public boolean hasEdgeRule(Vertex aVertex, Vertex bVertex) {
- String outType = aVertex.<String>property("aai-node-type").orElse(null);
- String inType = bVertex.<String>property("aai-node-type").orElse(null);
-
- return this.hasEdgeRule(outType, inType);
-
+ return this.hasEdgeRule(aVertex, bVertex, null);
+
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given nodes with label, in either A|B or B|A order with edge label.
+ *
+ * @param aVertex - node at one end of the edge
+ * @param bVertex - node at the other end
+ * @param label - edge label
+ * @return true, if any such rules exist
+ */
+ public boolean hasEdgeRule(Vertex aVertex, Vertex bVertex, String label) {
+ String outType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String inType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+
+ if (label == null) {
+ return this.hasEdgeRule(outType, inType);
+ } else {
+ return this.hasEdgeRule(outType, inType, label);
+ }
+ }
+
+ /**
+ * Checks if any edge rules exist between the two given node types, in either A|B or B|A order with edge label and edge type.
+ *
+ * @param type - type of edge EdgeType.COUSIN | EdgeType.TREE
+ * @param nodeA - node at one end of the edge
+ * @param nodeB - node at the other end
+ * @param label - edge label
+ * @return true, if any such rules exist
+ */
+ public boolean hasEdgeRule(EdgeType type, String nodeA, String nodeB, String label) {
+ Filter aToB = filter(
+ where("from").is(nodeA)
+ .and("to").is(nodeB)
+ );
+ Filter bToA = filter(
+ where("from").is(nodeB)
+ .and("to").is(nodeA)
+ );
+
+ if (EdgeType.TREE.equals(type)) {
+ aToB = aToB.and(where(EdgeProperty.CONTAINS.toString()).ne(AAIDirection.NONE.toString()));
+ bToA = bToA.and(where(EdgeProperty.CONTAINS.toString()).ne(AAIDirection.NONE.toString()));
+ } else if (EdgeType.COUSIN.equals(type)) {
+ aToB = aToB.and(where(EdgeProperty.CONTAINS.toString()).is(AAIDirection.NONE.toString()));
+ bToA = bToA.and(where(EdgeProperty.CONTAINS.toString()).is(AAIDirection.NONE.toString()));
+ }
+
+ if (label != null) {
+ aToB = aToB.and(where(LABEL).is(label));
+ bToA = bToA.and(where(LABEL).is(label));
+ }
+
+ List<Object> results = rulesDoc.read("$.rules.[?]", aToB);
+ results.addAll(rulesDoc.read("$.rules.[?]", bToA));
+
+ return !results.isEmpty();
}
/**
@@ -298,30 +392,110 @@ public class EdgeRules {
* The rules will be phrased in terms of out|in, though this will
* also find rules defined as in|out (it will flip the direction in
* the EdgeRule object returned accordingly to match out|in).
- *
- * @param outType
+ *
+ * @param outType
+ * @param inType
+ * @return Map<String edgeLabel, EdgeRule rule> where edgeLabel is the label name
+ * @throws AAIException
+ */
+ public Map<String, EdgeRule> getEdgeRules(String outType, String inType) {
+ return this.getEdgeRules(outType, inType, null);
+ }
+
+ /**
+ * Gets all the edge rules that exist between the given node types with given label.
+ * The rules will be phrased in terms of out|in, though this will
+ * also find rules defined as in|out (it will flip the direction in
+ * the EdgeRule object returned accordingly to match out|in).
+ *
+ * @param outType
* @param inType
+ * @param label
* @return Map<String edgeLabel, EdgeRule rule> where edgeLabel is the label name
* @throws AAIException
*/
- public Map<String, EdgeRule> getEdgeRules(String outType, String inType) throws AAIException {
- Map<String, EdgeRule> result = new HashMap<>();
- EdgeRule rule = null;
+ public Map<String, EdgeRule> getEdgeRules(String outType, String inType, String label) {
+ final Map<String, EdgeRule> result = new HashMap<>();
+
for (EdgeType type : EdgeType.values()) {
- try {
- rule = this.getEdgeRule(type, outType, inType);
- result.put(rule.getLabel(), rule);
- } catch (NoEdgeRuleFoundException e) {
- continue;
- }
+ result.putAll(this.getEdgeRules(type, outType, inType, label));
}
-
+
return result;
}
-
+ /**
+ * Looks up edge rules for the given node types and the labels specified
+ * @param type
+ * @param outType
+ * @param inType
+ * @param labels
+ * @return
+ * @throws NoEdgeRuleFoundException
+ * @throws MultipleEdgeRuleFoundException
+ */
+ public Map<String, EdgeRule> getEdgeRulesWithLabels(EdgeType type, String outType, String inType, List<String> labels) throws NoEdgeRuleFoundException, MultipleEdgeRuleFoundException {
+ final Map<String, EdgeRule> result = new HashMap<>();
+
+ if (labels == null || labels.isEmpty()) {
+ throw new NoEdgeRuleFoundException("No labels specified");
+ }
+ for (String label : labels) {
+ EdgeRule er = this.getEdgeRule(type, outType, inType, label);
+ result.put(er.getLabel(), er);
+ }
+
+ return result;
+ }
/**
+ * Gets all the edge rules of that edge type that exist between the given node types with given label.
+ * The rules will be phrased in terms of out|in, though this will
+ * also find rules defined as in|out (it will flip the direction in
+ * the EdgeRule object returned accordingly to match out|in).
+ *
+ * @param type
+ * @param outType
+ * @param inType
+ * @param label
+ * @return
+ * @throws AAIException
+ */
+ public Map<String, EdgeRule> getEdgeRules(EdgeType type, String outType, String inType, String label) {
+ final Map<String, EdgeRule> result = new HashMap<>();
+
+ this.getEdgeRulesFromJson(type, outType, inType, label).forEach(edgeRuleJson -> {
+ EdgeRule edgeRule = this.buildRule(edgeRuleJson);
+ result.put(edgeRule.getLabel(), edgeRule);
+ });
+ this.getEdgeRulesFromJson(type, inType, outType, label).forEach(erj -> {
+ EdgeRule edgeRule = this.flipDirection(this.buildRule(erj));
+ if (!result.containsKey(edgeRule.getLabel())) {
+ result.put(edgeRule.getLabel(), edgeRule);
+ }
+ });
+
+
+ return result;
+ }
+
+ /**
+ * Gets all the edge rules of that edge type that exist between the given node types.
+ * The rules will be phrased in terms of out|in, though this will
+ * also find rules defined as in|out (it will flip the direction in
+ * the EdgeRule object returned accordingly to match out|in).
+ *
+ * @param type
+ * @param outType
+ * @param inType
+ * @return
+ * @throws AAIException
+ */
+ public Map<String, EdgeRule> getEdgeRules(EdgeType type, String outType, String inType) {
+ return this.getEdgeRules(type, outType, inType, null);
+ }
+
+ /**
* 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
* to match the expected A|B return.
@@ -333,69 +507,155 @@ public class EdgeRules {
* @throws AAIException if no such edge exists
*/
public EdgeRule getEdgeRule(EdgeType type, String nodeA, String nodeB) throws AAIException {
- //try A to B
- List<Map<String, String>> 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<Map<String, String>> 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
+ return this.getEdgeRule(type, nodeA, nodeB, null);
+ }
+
+ /**
+ * Gets the edge rule of the given type that exists between A and B with edge label.
+ * Will check B|A as well, and flips the direction accordingly if that succeeds
+ * to match the expected A|B return.
+ *
+ * @param type - the type of edge you're looking for
+ * @param nodeA - first node type
+ * @param nodeB - second node type
+ * @param label - edge label
+ * @return EdgeRule describing the rule in terms of A|B, if there is any such rule
+ * @throws MultipleEdgeRuleFoundException
+ * @throws AAIException if no such edge exists
+ */
+ public EdgeRule getEdgeRule(EdgeType type, String nodeA, String nodeB, String label) throws NoEdgeRuleFoundException, MultipleEdgeRuleFoundException {
+
+ final StringBuilder errorMsg = new StringBuilder();
+ errorMsg.append(type.toString())
+ .append(" edge rule between ")
+ .append(nodeA).append(" and ").append(nodeB);
+ if (label != null) {
+ errorMsg.append(" with label ").append(label);
}
-
+
+ EdgeRule edgeRule;
+ Map<String, EdgeRule> edgeRules = this.getEdgeRules(type, nodeA, nodeB, label);
+
//found none
- throw new NoEdgeRuleFoundException("no " + type.toString() + " edge between " + nodeA + " and " + nodeB);
+ if (edgeRules.isEmpty()) {
+
+ throw new NoEdgeRuleFoundException("no " + errorMsg);
+
+ } else if (edgeRules.size() == 1) {
+
+ edgeRule = edgeRules.values().iterator().next();
+
+ } else {
+
+ Optional<EdgeRule> optionalEdgeRule = Optional.empty();
+
+ try {
+ optionalEdgeRule = this.getDefaultEdgeRule(edgeRules);
+ } catch (MultipleEdgeRuleFoundException e) {
+ throw new MultipleEdgeRuleFoundException("multiple default edge rule exists " + errorMsg);
+ }
+
+ edgeRule = optionalEdgeRule.orElseThrow(() -> new MultipleEdgeRuleFoundException("multiple edge rule exists with no default " + errorMsg));
+
+ }
+
+ return edgeRule;
}
-
+
+ private Optional<EdgeRule> getDefaultEdgeRule(Map<String, EdgeRule> edgeRules) throws MultipleEdgeRuleFoundException {
+
+ EdgeRule edgeRule = null;
+ int numDefaults = 0;
+
+ for (Map.Entry<String, EdgeRule> entry : edgeRules.entrySet()) {
+ if (entry.getValue().isDefault()) {
+ edgeRule = entry.getValue();
+ numDefaults++;
+ }
+ }
+
+ if (numDefaults > 1) {
+ throw new MultipleEdgeRuleFoundException("");
+ }
+
+ if (edgeRule == null) {
+ return Optional.empty();
+ } else {
+ return Optional.of(edgeRule);
+ }
+ }
+
+ /**
+ * Gets the rules from the edge rules Json
+ *
+ * @param type - type
+ * @param nodeA - start node
+ * @param nodeB - end node
+ * @param label - edge label to filter on
+ * @return
+ */
+ private List<Map<String, String>> getEdgeRulesFromJson(EdgeType type, String nodeA, String nodeB, String label) {
+ if (label == null) {
+ return rulesDoc.read("$.rules.[?]", buildFilter(type, nodeA, nodeB));
+ } else {
+ return rulesDoc.read("$.rules.[?]", buildFilter(type, nodeA, nodeB, label));
+ }
+ }
+
/**
* Builds a JsonPath filter to search for an edge from nodeA to nodeB with the given edge type (cousin or parent/child)
- *
+ *
* @param type
* @param nodeA - start node
* @param nodeB - end node
* @return
*/
private Filter buildFilter(EdgeType type, String nodeA, String nodeB) {
+ return this.buildFilter(type, nodeA, nodeB, null);
+ }
+
+ private Filter buildFilter(EdgeType type, String nodeA, String nodeB, String label) {
if (EdgeType.COUSIN.equals(type)) {
- return filter(
- where("from").is(nodeA).and("to").is(nodeB).and(EdgeProperty.CONTAINS.toString()).is(AAIDirection.NONE.toString())
+ Filter f = filter(
+ where("from").is(nodeA)
+ .and("to").is(nodeB)
+ .and(EdgeProperty.CONTAINS.toString()).is(AAIDirection.NONE.toString())
);
+ if (label != null) {
+ f = f.and(where(LABEL).is(label));
+ }
+
+ return f;
} else {
return filter(
- where("from").is(nodeA).and("to").is(nodeB).and(EdgeProperty.CONTAINS.toString()).is("${direction}")).or(
- where("from").is(nodeA).and("to").is(nodeB).and(EdgeProperty.CONTAINS.toString()).is("!${direction}")
+ where("from").is(nodeA).and("to").is(nodeB).and(EdgeProperty.CONTAINS.toString()).is(DIRECTION_NOTATION)).or(
+ where("from").is(nodeA).and("to").is(nodeB).and(EdgeProperty.CONTAINS.toString()).is(NOT_DIRECTION_NOTATION)
);
}
}
-
+
/**
- * Puts the give edge rule information into an EdgeRule object.
- *
- * @param edge - the edge information returned from JsonPath
+ * Puts the give edge rule information into an EdgeRule object.
+ *
+ * @param map edge rule property map
* @return EdgeRule containing that information
*/
private EdgeRule buildRule(Map<String, String> map) {
Map<String, String> edge = new EdgePropertyMap<>();
edge.putAll(map);
-
+
EdgeRule rule = new EdgeRule();
- rule.setLabel(edge.get("label"));
+ rule.setLabel(edge.get(LABEL));
rule.setDirection(edge.get("direction"));
rule.setMultiplicityRule(edge.get("multiplicity"));
rule.setContains(edge.get(EdgeProperty.CONTAINS.toString()));
rule.setDeleteOtherV(edge.get(EdgeProperty.DELETE_OTHER_V.toString()));
rule.setServiceInfrastructure(edge.get(EdgeProperty.SVC_INFRA.toString()));
rule.setPreventDelete(edge.get(EdgeProperty.PREVENT_DELETE.toString()));
-
+ if (edge.containsKey("default")) {
+ rule.setIsDefault(edge.get("default"));
+ }
+
return rule;
}
@@ -403,7 +663,7 @@ public class EdgeRules {
* If getEdgeRule gets a request for A|B, and it finds something as B|A, the caller still expects
* the returned EdgeRule to reflect A|B directionality. This helper method flips B|A direction to
* match this expectation.
- *
+ *
* @param rule whose direction needs flipped
* @return the updated rule
*/
@@ -415,7 +675,7 @@ public class EdgeRules {
rule.setDirection(Direction.IN);
return rule;
} else { //direction is BOTH, flipping both is still both
- return rule;
+ return rule;
}
}
@@ -431,14 +691,30 @@ public class EdgeRules {
* @throws AAIException if no such edge exists
*/
public EdgeRule getEdgeRule(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
+ return this.getEdgeRule(type, aVertex, bVertex, null);
+ }
+
+ /**
+ * Gets the edge rule of the given type that exists between A and B with label.
+ * Will check B|A as well, and flips the direction accordingly if that succeeds
+ * to match the expected A|B return.
+ *
+ * @param type - the type of edge you're looking for
+ * @param aVertex - first node type
+ * @param bVertex - second node type
+ * @param label - edge label
+ * @return EdgeRule describing the rule in terms of A|B, if there is any such rule
+ * @throws AAIException if no such edge exists
+ */
+ public EdgeRule getEdgeRule(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
String outType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
String inType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
-
- return this.getEdgeRule(type, outType, inType);
-
+ return this.getEdgeRule(type, outType, inType, label);
+
+
}
-
+
/**
* Validate multiplicity.
*
@@ -450,44 +726,46 @@ public class EdgeRules {
*/
private Optional<String> validateMultiplicity(EdgeRule rule, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) {
+ Vertex a = aVertex;
+ Vertex b = bVertex;
+
if (rule.getDirection().equals(Direction.OUT)) {
-
+ a = aVertex;
+ b = bVertex;
} else if (rule.getDirection().equals(Direction.IN)) {
- Vertex tempV = bVertex;
- bVertex = aVertex;
- aVertex = tempV;
+ a = bVertex;
+ b = aVertex;
}
-
- String aVertexType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- String bVertexType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+
+ String aVertexType = a.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String bVertexType = b.<String>property(AAIProperties.NODE_TYPE).orElse(null);
String label = rule.getLabel();
MultiplicityRule multiplicityRule = rule.getMultiplicityRule();
- List<Edge> outEdges = traversalSource.V(aVertex).outE(label).where(__.inV().has(AAIProperties.NODE_TYPE, bVertexType)).toList();
- List<Edge> inEdges = traversalSource.V(bVertex).inE(label).where(__.outV().has(AAIProperties.NODE_TYPE, aVertexType)).toList();
+ List<Edge> outEdges = traversalSource.V(a).outE(label).where(__.inV().has(AAIProperties.NODE_TYPE, bVertexType)).toList();
+ List<Edge> inEdges = traversalSource.V(b).inE(label).where(__.outV().has(AAIProperties.NODE_TYPE, aVertexType)).toList();
String detail = "";
+ final String msg = "multiplicity rule violated: only one edge can exist with label: ";
if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) {
- if (inEdges.size() >= 1 || outEdges.size() >= 1 ) {
- detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
+ if (!inEdges.isEmpty() || !outEdges.isEmpty() ) {
+ detail = msg + label + " between " + aVertexType + " and " + bVertexType;
}
} else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) {
- if (inEdges.size() >= 1) {
- detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
+ if (!inEdges.isEmpty()) {
+ detail = msg + label + " between " + aVertexType + " and " + bVertexType;
}
} else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) {
- if (outEdges.size() >= 1) {
- detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
+ if (!outEdges.isEmpty()) {
+ detail = msg + label + " between " + aVertexType + " and " + bVertexType;
}
- } else {
-
}
-
+
if (!"".equals(detail)) {
return Optional.of(detail);
} else {
return Optional.empty();
}
-
-
+
+
}
/**
@@ -513,7 +791,7 @@ public class EdgeRules {
}
}
}
-
+
/**
* Reads all the edge rules from the loaded json file.
*
@@ -547,22 +825,22 @@ public class EdgeRules {
/**
* Gets all the edge rules we define.
- *
+ *
* @return Multimap<String "from|to", EdgeRule rule>
*/
public Multimap<String, EdgeRule> getAllRules() {
Multimap<String, EdgeRule> result = ArrayListMultimap.create();
-
+
List<Map<String, String>> rules = readRules();
for (Map<String, String> rule : rules) {
EdgeRule er = buildRule(rule);
String name = rule.get("from") + "|" + rule.get("to");
result.put(name, er);
}
-
+
return result;
}
-
+
/**
* Gets all edge rules that define a child relationship from
* the given node type.
@@ -571,19 +849,40 @@ public class EdgeRules {
* @return
*/
public Set<EdgeRule> 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}"));
-
+ where("from").is(nodeType).and(EdgeProperty.CONTAINS.toString()).is(DIRECTION_NOTATION)
+ ).or(where("to").is(nodeType).and(EdgeProperty.CONTAINS.toString()).is(NOT_DIRECTION_NOTATION));
+
final List<Map<String, String>> rules = readRules(filter);
final Set<EdgeRule> result = new HashSet<>();
rules.forEach(item -> {
verifyRule(item);
result.add(buildRule(item));
});
-
+
return result;
-
+
+ }
+
+ private static class Helper {
+ private static final EdgeRules INSTANCE = new EdgeRules();
+ private static final Map<Version, EdgeRules> INSTANCEMAP = new ConcurrentHashMap<>();
+
+ private Helper() {}
+
+ private static EdgeRules getEdgeRulesByFilename(String rulesFilename) {
+ return new EdgeRules(rulesFilename);
+ }
+
+ private static EdgeRules getVersionedEdgeRules(Version v) {
+ if (Version.isLatest(v)) {
+ return INSTANCE;
+ }
+ if (!INSTANCEMAP.containsKey(v)) {
+ INSTANCEMAP.put(v, new EdgeRules(v));
+ }
+ return INSTANCEMAP.get(v);
+ }
}
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/MultipleEdgeRuleFoundException.java b/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/MultipleEdgeRuleFoundException.java
new file mode 100644
index 00000000..bb4ba4df
--- /dev/null
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/MultipleEdgeRuleFoundException.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright (C) 2017 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.serialization.db.exceptions;
+
+import org.onap.aai.exceptions.AAIException;
+
+public class MultipleEdgeRuleFoundException extends AAIException {
+
+ private static final long serialVersionUID = -906843868234976763L;
+
+ public MultipleEdgeRuleFoundException(String message) {
+ super("AAI_6107", message);
+ }
+
+ public MultipleEdgeRuleFoundException(Throwable cause) {
+ super("AAI_6107",cause);
+ }
+
+ public MultipleEdgeRuleFoundException(String message, Throwable cause) {
+ super("AAI_6107", cause, message);
+ }
+}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/NoEdgeRuleFoundException.java b/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/NoEdgeRuleFoundException.java
index 247379cb..b66f0147 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/NoEdgeRuleFoundException.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/exceptions/NoEdgeRuleFoundException.java
@@ -28,14 +28,14 @@ public class NoEdgeRuleFoundException extends AAIException {
private static final long serialVersionUID = -906843868234976763L;
public NoEdgeRuleFoundException(String message) {
- super("AAI_6129", message);
+ super("AAI_6107", message);
}
public NoEdgeRuleFoundException(Throwable cause) {
- super("AAI_6129",cause);
+ super("AAI_6107",cause);
}
public NoEdgeRuleFoundException(String message, Throwable cause) {
- super("AAI_6129", cause, message);
+ super("AAI_6107", cause, message);
}
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/util/VersionChecker.java b/aai-core/src/main/java/org/onap/aai/serialization/db/util/VersionChecker.java
new file mode 100644
index 00000000..04c57ed8
--- /dev/null
+++ b/aai-core/src/main/java/org/onap/aai/serialization/db/util/VersionChecker.java
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.serialization.db.util;
+
+import org.onap.aai.introspection.Version;
+
+public class VersionChecker {
+
+ private VersionChecker() {}
+
+ /**
+ * true if Version v is gt v12
+ *
+ * @param v - Version to be checked
+ * @return
+ */
+ public static boolean apiVersionNeedsEdgeLabel(Version v) {
+ return v.compareTo(Version.v12) >= 0 ;
+ }
+}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java
index 7aaf3035..3477a748 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/RawFormat.java
@@ -25,6 +25,7 @@ import java.util.Iterator;
import java.util.List;
import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.onap.aai.db.props.AAIProperties;
@@ -101,23 +102,35 @@ public class RawFormat implements FormatMapper {
return json;
}
+
protected JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException {
JsonArray jarray = new JsonArray();
- Iterator<Vertex> iter = v.vertices(Direction.BOTH);
-
- while (iter.hasNext()) {
- Vertex related = iter.next();
+ Iterator<Edge> inIter = v.edges(Direction.IN);
+ Iterator<Edge> outIter = v.edges(Direction.OUT);
- JsonObject json = new JsonObject();
- json.addProperty("id", related.id().toString());
- json.addProperty("node-type", related.<String>value(AAIProperties.NODE_TYPE));
- json.addProperty("url", this.urlBuilder.pathed(related));
- jarray.add(json);
+ while (inIter.hasNext()) {
+ Edge e = inIter.next();
+ jarray.add(this.getRelatedObject(e.label(), e.outVertex()));
+ }
+
+ while (outIter.hasNext()) {
+ Edge e = outIter.next();
+ jarray.add(this.getRelatedObject(e.label(), e.inVertex()));
}
return jarray;
}
+ private JsonObject getRelatedObject(String label, Vertex related) throws AAIFormatVertexException {
+ JsonObject json = new JsonObject();
+ json.addProperty("id", related.id().toString());
+ json.addProperty("relationship-label", label);
+ json.addProperty("node-type", related.<String>value(AAIProperties.NODE_TYPE));
+ json.addProperty("url", this.urlBuilder.pathed(related));
+
+ return json;
+ }
+
public static class Builder implements NodesOnly<Builder>, Depth<Builder> {
protected final Loader loader;
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/exceptions/AAIFormatQueryResultFormatNotSupported.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/exceptions/AAIFormatQueryResultFormatNotSupported.java
new file mode 100644
index 00000000..726116a0
--- /dev/null
+++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/exceptions/AAIFormatQueryResultFormatNotSupported.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright (C) 2017 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.serialization.queryformats.exceptions;
+
+public class AAIFormatQueryResultFormatNotSupported extends Exception {
+
+ private static final long serialVersionUID = -5814240842844624097L;
+
+ public AAIFormatQueryResultFormatNotSupported() {}
+
+ public AAIFormatQueryResultFormatNotSupported(String message) {
+ super(message);
+ }
+
+ public AAIFormatQueryResultFormatNotSupported(Throwable cause) {
+ super(cause);
+ }
+
+ public AAIFormatQueryResultFormatNotSupported(String message, Throwable cause) {
+ super(message, cause);
+ }
+}