2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.serialization.db;
23 import com.att.eelf.configuration.EELFLogger;
24 import com.att.eelf.configuration.EELFManager;
25 import com.google.common.base.CaseFormat;
26 import org.apache.commons.collections.IteratorUtils;
27 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
28 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
29 import org.apache.tinkerpop.gremlin.structure.Direction;
30 import org.apache.tinkerpop.gremlin.structure.Edge;
31 import org.apache.tinkerpop.gremlin.structure.Vertex;
32 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
33 import org.janusgraph.core.SchemaViolationException;
34 import org.javatuples.Triplet;
35 import org.onap.aai.concurrent.AaiCallable;
36 import org.onap.aai.config.SpringContextAware;
37 import org.onap.aai.db.props.AAIProperties;
38 import org.onap.aai.edges.EdgeIngestor;
39 import org.onap.aai.edges.EdgeRule;
40 import org.onap.aai.edges.EdgeRuleQuery;
41 import org.onap.aai.edges.TypeAlphabetizer;
42 import org.onap.aai.edges.enums.AAIDirection;
43 import org.onap.aai.edges.enums.EdgeField;
44 import org.onap.aai.edges.enums.EdgeProperty;
45 import org.onap.aai.edges.enums.EdgeType;
46 import org.onap.aai.edges.exceptions.AmbiguousRuleChoiceException;
47 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
48 import org.onap.aai.exceptions.AAIException;
49 import org.onap.aai.introspection.*;
50 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
51 import org.onap.aai.introspection.sideeffect.*;
52 import org.onap.aai.logging.ErrorLogHelper;
53 import org.onap.aai.logging.LogFormatTools;
54 import org.onap.aai.logging.LoggingContext;
55 import org.onap.aai.logging.StopWatch;
56 import org.onap.aai.parsers.query.QueryParser;
57 import org.onap.aai.parsers.uri.URIParser;
58 import org.onap.aai.parsers.uri.URIToRelationshipObject;
59 import org.onap.aai.query.builder.QueryBuilder;
60 import org.onap.aai.schema.enums.ObjectMetadata;
61 import org.onap.aai.schema.enums.PropertyMetadata;
62 import org.onap.aai.serialization.db.exceptions.MultipleEdgeRuleFoundException;
63 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
64 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
65 import org.onap.aai.serialization.engines.query.QueryEngine;
66 import org.onap.aai.setup.SchemaVersion;
67 import org.onap.aai.setup.SchemaVersions;
68 import org.onap.aai.util.AAIConfig;
69 import org.onap.aai.util.AAIConstants;
70 import org.onap.aai.workarounds.NamingExceptions;
71 import org.springframework.context.ApplicationContext;
73 import javax.ws.rs.core.UriBuilder;
74 import java.io.UnsupportedEncodingException;
75 import java.lang.reflect.Array;
76 import java.lang.reflect.InvocationTargetException;
77 import java.net.MalformedURLException;
79 import java.net.URISyntaxException;
81 import java.util.concurrent.ExecutionException;
82 import java.util.concurrent.ExecutorService;
83 import java.util.concurrent.Future;
84 import java.util.regex.Matcher;
85 import java.util.regex.Pattern;
87 public class DBSerializer {
89 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DBSerializer.class);
91 private static final String IMPLICIT_DELETE = "Implicit DELETE";
93 private static final String MISSING_REQUIRED_NODE_PROPERTY = "Vertex missing required aai-node-type property";
95 private final TransactionalGraphEngine engine;
96 private final String sourceOfTruth;
97 private final ModelType introspectionType;
98 private final SchemaVersion version;
99 private final Loader latestLoader;
100 private EdgeSerializer edgeSer;
101 private EdgeIngestor edgeRules;
102 private final Loader loader;
103 private final String baseURL;
104 private double dbTimeMsecs = 0;
105 private long currentTimeMillis;
107 private SchemaVersions schemaVersions;
108 private Set<String> namedPropNodes;
110 * Instantiates a new DB serializer.
112 * @param version the version
113 * @param engine the engine
114 * @param introspectionType the introspection type
115 * @param sourceOfTruth the source of truth
116 * @throws AAIException
118 public DBSerializer(SchemaVersion version, TransactionalGraphEngine engine, ModelType introspectionType, String sourceOfTruth) throws AAIException {
119 this.engine = engine;
120 this.sourceOfTruth = sourceOfTruth;
121 this.introspectionType = introspectionType;
122 this.schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions");
123 SchemaVersion LATEST = schemaVersions.getDefaultVersion();
124 this.latestLoader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, LATEST);
125 this.version = version;
126 this.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version);
127 this.namedPropNodes = this.latestLoader.getNamedPropNodes();
128 this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE);
129 this.currentTimeMillis = System.currentTimeMillis();
133 private void initBeans() {
134 //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
135 ApplicationContext ctx = SpringContextAware.getApplicationContext();
136 EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
138 EdgeSerializer es = ctx.getBean(EdgeSerializer.class);
139 setEdgeSerializer(es);
142 private void backupESInit() {
143 setEdgeSerializer(new EdgeSerializer(this.edgeRules));
146 public void setEdgeSerializer(EdgeSerializer edgeSer) {
147 this.edgeSer = edgeSer;
150 public EdgeSerializer getEdgeSeriailizer() {
154 public void setEdgeIngestor(EdgeIngestor ei) {
158 public EdgeIngestor getEdgeIngestor() {
159 return this.edgeRules;
163 * Touch standard vertex properties.
166 * @param isNewVertex the is new vertex
168 public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) {
169 String timeNowInSec = Long.toString(currentTimeMillis);
172 v.property(AAIProperties.SOURCE_OF_TRUTH, this.sourceOfTruth);
173 v.property(AAIProperties.CREATED_TS, timeNowInSec);
174 v.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString());
176 v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec);
177 v.property(AAIProperties.LAST_MOD_TS, timeNowInSec);
178 v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth);
182 private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) {
184 v.property(AAIProperties.NODE_TYPE, nodeType);
185 touchStandardVertexProperties(v, isNewVertex);
191 * Creates the new vertex.
193 * @param wrappedObject the wrapped object
195 * @throws UnsupportedEncodingException the unsupported encoding exception
196 * @throws AAIException the AAI exception
198 public Vertex createNewVertex(Introspector wrappedObject) {
201 StopWatch.conditionalStart();
202 v = this.engine.tx().addVertex();
203 touchStandardVertexProperties(wrappedObject.getDbName(), v, true);
205 dbTimeMsecs += StopWatch.stopIfStarted();
213 * @param className the class name
217 * Removes the classpath from a class name
219 public String trimClassName(String className) {
220 String returnValue = "";
222 if (className.lastIndexOf('.') == -1) {
225 returnValue = className.substring(className.lastIndexOf('.') + 1, className.length());
235 * @param uriQuery the uri query
236 * @param identifier the identifier
237 * @throws SecurityException the security exception
238 * @throws IllegalAccessException the illegal access exception
239 * @throws IllegalArgumentException the illegal argument exception
240 * @throws InvocationTargetException the invocation target exception
241 * @throws InstantiationException the instantiation exception
242 * @throws InterruptedException the interrupted exception
243 * @throws NoSuchMethodException the no such method exception
244 * @throws AAIException the AAI exception
245 * @throws UnsupportedEncodingException the unsupported encoding exception
246 * @throws AAIUnknownObjectException
248 public void serializeToDb(Introspector obj, Vertex v, QueryParser uriQuery, String identifier, String requestContext) throws AAIException, UnsupportedEncodingException {
249 StopWatch.conditionalStart();
251 if (uriQuery.isDependent()) {
252 //try to find the parent
253 List<Vertex> vertices = uriQuery.getQueryBuilder().getParentQuery().toList();
254 if (!vertices.isEmpty()) {
255 Vertex parent = vertices.get(0);
256 this.reflectDependentVertex(parent, v, obj, requestContext);
258 dbTimeMsecs += StopWatch.stopIfStarted();
259 throw new AAIException("AAI_6114", "No parent Node of type " + uriQuery.getParentResultType() + " for " + identifier);
262 serializeSingleVertex(v, obj, requestContext);
265 } catch (SchemaViolationException e) {
266 dbTimeMsecs += StopWatch.stopIfStarted();
267 throw new AAIException("AAI_6117", e);
269 dbTimeMsecs += StopWatch.stopIfStarted();
272 public void serializeSingleVertex(Vertex v, Introspector obj, String requestContext) throws UnsupportedEncodingException, AAIException {
273 StopWatch.conditionalStart();
275 boolean isTopLevel = obj.isTopLevel();
277 addUriIfNeeded(v, obj.getURI());
280 processObject(obj, v, requestContext);
282 URI uri = this.getURIForVertex(v);
283 URIParser parser = new URIParser(this.loader, uri);
284 if (parser.validate()) {
285 addUriIfNeeded(v, uri.toString());
288 } catch (SchemaViolationException e) {
289 throw new AAIException("AAI_6117", e);
291 dbTimeMsecs += StopWatch.stopIfStarted();
295 private void addUriIfNeeded(Vertex v, String uri) {
296 VertexProperty<String> uriProp = v.property(AAIProperties.AAI_URI);
297 if (!uriProp.isPresent() || (uriProp.isPresent() && !uriProp.value().equals(uri))) {
298 v.property(AAIProperties.AAI_URI, uri);
305 * @param <T> the generic type
309 * @throws IllegalAccessException the illegal access exception
310 * @throws IllegalArgumentException the illegal argument exception
311 * @throws InvocationTargetException the invocation target exception
312 * @throws InstantiationException the instantiation exception
313 * @throws NoSuchMethodException the no such method exception
314 * @throws SecurityException the security exception
315 * @throws AAIException the AAI exception
316 * @throws UnsupportedEncodingException the unsupported encoding exception
317 * @throws AAIUnknownObjectException
320 * Helper method for reflectToDb
321 * Handles all the property setting
323 private <T> List<Vertex> processObject(Introspector obj, Vertex v, String requestContext) throws UnsupportedEncodingException, AAIException {
324 Set<String> properties = new LinkedHashSet<>(obj.getProperties());
325 properties.remove(AAIProperties.RESOURCE_VERSION);
326 List<Vertex> dependentVertexes = new ArrayList<>();
327 List<Vertex> processedVertexes = new ArrayList<>();
328 boolean isComplexType = false;
329 boolean isListType = false;
330 if (!obj.isContainer()) {
331 this.touchStandardVertexProperties(v, false);
333 this.executePreSideEffects(obj, v);
334 for (String property : properties) {
336 final String propertyType;
337 propertyType = obj.getType(property);
338 isComplexType = obj.isComplexType(property);
339 isListType = obj.isListType(property);
340 value = obj.getValue(property);
342 if (!(isComplexType || isListType)) {
343 boolean canModify = this.canModify(obj, property, requestContext);
346 final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
347 String dbProperty = property;
348 if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
349 dbProperty = metadata.get(PropertyMetadata.DB_ALIAS);
351 if (metadata.containsKey(PropertyMetadata.DATA_LINK)) {
352 //data linked properties are ephemeral
353 //they are populated dynamically on GETs
357 if (!value.equals(v.property(dbProperty).orElse(null))) {
358 if (propertyType.toLowerCase().contains(".long")) {
359 v.property(dbProperty, new Integer(((Long) value).toString()));
361 v.property(dbProperty, value);
365 v.property(dbProperty).remove();
368 } else if (isListType) {
369 List<Object> list = (List<Object>) value;
370 if (obj.isComplexGenericType(property)) {
372 for (Object o : list) {
373 Introspector child = IntrospectorFactory.newInstance(this.introspectionType, o);
374 child.setURIChain(obj.getURI());
375 processedVertexes.add(reflectDependentVertex(v, child, requestContext));
380 engine.setListProperty(v, property, list);
383 //method.getReturnType() is not 'simple' then create a vertex and edge recursively returning an edge back to this method
384 if (value != null) { //effectively ignore complex properties not included in the object we're processing
385 if (value.getClass().isArray()) {
387 int length = Array.getLength(value);
388 for (int i = 0; i < length; i++) {
389 Object arrayElement = Array.get(value, i);
390 Introspector child = IntrospectorFactory.newInstance(this.introspectionType, arrayElement);
391 child.setURIChain(obj.getURI());
392 processedVertexes.add(reflectDependentVertex(v, child, requestContext));
395 } else if (!property.equals("relationship-list")) {
397 Introspector introspector = IntrospectorFactory.newInstance(this.introspectionType, value);
398 if (introspector.isContainer()) {
399 dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getChildDBName()));
400 introspector.setURIChain(obj.getURI());
402 processedVertexes.addAll(processObject(introspector, v, requestContext));
405 dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getDbName()));
406 processedVertexes.add(reflectDependentVertex(v, introspector, requestContext));
409 } else if (property.equals("relationship-list")) {
410 handleRelationships(obj, v);
415 this.writeThroughDefaults(v, obj);
416 /* handle those vertexes not touched */
417 for (Vertex toBeRemoved : processedVertexes) {
418 dependentVertexes.remove(toBeRemoved);
421 // If the dependent vertices are not empty, then with
422 // the current behaviour, it should remove the vertices implicitly
423 // We are updating the code to properly log which call
424 // is doing this so the SE can work with the clients making the call to
425 // tell them not to call this API and can hopefully deprecate this
426 // functionality in the future releases
427 if(!dependentVertexes.isEmpty()){
429 LoggingContext.responseDescription(IMPLICIT_DELETE);
431 // Find all the deletable vertices from the dependent vertices that should be deleted
432 // So for each of the following dependent vertices,
433 // we will use the edge properties and do the cascade delete
434 List<Vertex> impliedDeleteVertices = this.engine.getQueryEngine().findDeletable(dependentVertexes);
435 int impliedDeleteCount = impliedDeleteVertices.size();
438 "For the vertex with id {}, doing an implicit delete on update will delete total of {} vertexes",
443 String impliedDeleteLogEnabled = AAIConfig.get(AAIConstants.AAI_IMPLIED_DELETE_LOG_ENABLED, "true");
445 int impliedDeleteLogLimit = AAIConfig.getInt(AAIConstants.AAI_IMPLIED_DELETE_LOG_LIMIT, "-1");
447 if(impliedDeleteLogLimit == -1){
448 impliedDeleteLogLimit = Integer.MAX_VALUE;
451 // If the logging is enabled for implied delete
452 // then log the payload in the latest format
453 if("true".equals(impliedDeleteLogEnabled) &&
454 impliedDeleteCount <= impliedDeleteLogLimit){
455 for(Vertex vertex : impliedDeleteVertices){
456 Introspector introspector = null;
458 introspector = getLatestVersionView(vertex);
459 if(LOGGER.isInfoEnabled()){
460 LOGGER.info("Implied delete object in json format {}", introspector.marshal(false));
462 } catch(Exception ex){
463 LOGGER.warn("Encountered an exception during retrieval of vertex properties with vertex-id {} -> {}", v.id(), LogFormatTools.getStackTop(ex));
468 // After all the appropriate logging, calling the delete to delete the affected vertices
469 this.delete(impliedDeleteVertices);
472 this.executePostSideEffects(obj, v);
473 return processedVertexes;
477 * Handle relationships.
480 * @param vertex the vertex
481 * @throws SecurityException the security exception
482 * @throws IllegalAccessException the illegal access exception
483 * @throws IllegalArgumentException the illegal argument exception
484 * @throws InvocationTargetException the invocation target exception
485 * @throws UnsupportedEncodingException the unsupported encoding exception
486 * @throws AAIException the AAI exception
489 * Handles the explicit relationships defined for an obj
491 private void handleRelationships(Introspector obj, Vertex vertex) throws UnsupportedEncodingException, AAIException {
494 Introspector wrappedRl = obj.getWrappedValue("relationship-list");
495 processRelationshipList(wrappedRl, vertex);
502 * Process relationship list.
504 * @param wrapped the wrapped
506 * @throws UnsupportedEncodingException the unsupported encoding exception
507 * @throws AAIException the AAI exception
509 private void processRelationshipList(Introspector wrapped, Vertex v) throws UnsupportedEncodingException, AAIException {
511 List<Object> relationships = (List<Object>) wrapped.getValue("relationship");
513 List<Triplet<Vertex, Vertex, String>> addEdges = new ArrayList<>();
514 List<Edge> existingEdges = this.engine.getQueryEngine().findEdgesForVersion(v, wrapped.getLoader());
516 for (Object relationship : relationships) {
518 Vertex cousinVertex = null;
520 Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship);
521 QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel);
523 if (wrappedRel.hasProperty("relationship-label")) {
524 label = wrappedRel.getValue("relationship-label");
527 List<Vertex> results = parser.getQueryBuilder().toList();
528 if (results.isEmpty()) {
529 final AAIException ex = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
530 ex.getTemplateVars().add(parser.getResultType());
531 ex.getTemplateVars().add(parser.getUri().toString());
534 //still an issue if there's more than one
535 cousinVertex = results.get(0);
538 if (cousinVertex != null) {
539 String vType = (String) v.property(AAIProperties.NODE_TYPE).value();
540 String cousinType = (String) cousinVertex.property(AAIProperties.NODE_TYPE).value();
541 EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(vType, cousinType).label(label);
544 if (!edgeRules.hasRule(baseQ.build())) {
545 throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + v.property(AAIProperties.NODE_TYPE).value().toString() + ", "
546 + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() + (label != null ? (" with label " + label) : "") + ".");
547 } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build()) && !edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) {
548 throw new AAIException("AAI_6145");
551 e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex, label);
554 addEdges.add(new Triplet<>(v, cousinVertex, label));
556 existingEdges.remove(e);
561 for (Edge edge : existingEdges) {
564 for (Triplet<Vertex, Vertex, String> triplet : addEdges) {
566 edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), triplet.getValue0(), triplet.getValue1(), triplet.getValue2());
567 } catch (NoEdgeRuleFoundException e) {
568 throw new AAIException("AAI_6129", e);
575 * Write through defaults.
579 * @throws AAIUnknownObjectException
581 private void writeThroughDefaults(Vertex v, Introspector obj) throws AAIUnknownObjectException {
582 Introspector latest = this.latestLoader.introspectorFromName(obj.getName());
583 if (latest != null) {
584 Set<String> required = latest.getRequiredProperties();
586 for (String field : required) {
587 String defaultValue = null;
588 Object vertexProp = null;
589 defaultValue = latest.getPropertyMetadata(field).get(PropertyMetadata.DEFAULT_VALUE);
590 if (defaultValue != null) {
591 vertexProp = v.<Object>property(field).orElse(null);
592 if (vertexProp == null) {
593 v.property(field, defaultValue);
603 * Reflect dependent vertex.
606 * @param dependentObj the dependent obj
608 * @throws IllegalAccessException the illegal access exception
609 * @throws IllegalArgumentException the illegal argument exception
610 * @throws InvocationTargetException the invocation target exception
611 * @throws InstantiationException the instantiation exception
612 * @throws NoSuchMethodException the no such method exception
613 * @throws SecurityException the security exception
614 * @throws AAIException the AAI exception
615 * @throws UnsupportedEncodingException the unsupported encoding exception
616 * @throws AAIUnknownObjectException
618 private Vertex reflectDependentVertex(Vertex v, Introspector dependentObj, String requestContext) throws AAIException, UnsupportedEncodingException {
620 //QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI());
621 //List<Vertex> items = p.getQuery().toList();
622 QueryBuilder<Vertex> query = this.engine.getQueryBuilder(v);
623 query.createEdgeTraversal(EdgeType.TREE, v, dependentObj);
624 query.createKeyQuery(dependentObj);
626 List<Vertex> items = query.toList();
628 Vertex dependentVertex = null;
629 if (items.size() == 1) {
630 dependentVertex = items.get(0);
631 this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI());
633 this.verifyResourceVersion("create", dependentObj.getDbName(), "", (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI());
634 dependentVertex = createNewVertex(dependentObj);
637 return reflectDependentVertex(v, dependentVertex, dependentObj, requestContext);
642 * Reflect dependent vertex.
644 * @param parent the parent
645 * @param child the child
648 * @throws IllegalAccessException the illegal access exception
649 * @throws IllegalArgumentException the illegal argument exception
650 * @throws InvocationTargetException the invocation target exception
651 * @throws InstantiationException the instantiation exception
652 * @throws NoSuchMethodException the no such method exception
653 * @throws SecurityException the security exception
654 * @throws AAIException the AAI exception
655 * @throws UnsupportedEncodingException the unsupported encoding exception
656 * @throws AAIUnknownObjectException
658 private Vertex reflectDependentVertex(Vertex parent, Vertex child, Introspector obj, String requestContext) throws AAIException, UnsupportedEncodingException {
660 String parentUri = parent.<String>property(AAIProperties.AAI_URI).orElse(null);
661 if (parentUri != null) {
664 addUriIfNeeded(child, parentUri + uri);
666 processObject(obj, child, requestContext);
669 e = this.getEdgeBetween(EdgeType.TREE, parent, child, null);
672 String canBeLinked = obj.getMetadata(ObjectMetadata.CAN_BE_LINKED);
673 if (canBeLinked != null && canBeLinked.equals("true")) {
674 Loader ldrForCntxt = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, getVerForContext(requestContext));
675 boolean isFirst = !this.engine.getQueryBuilder(ldrForCntxt, parent).createEdgeTraversal(EdgeType.TREE, parent, obj).hasNext();
677 child.property(AAIProperties.LINKED, true);
680 edgeSer.addTreeEdge(this.engine.asAdmin().getTraversalSource(), parent, child);
686 private SchemaVersion getVerForContext(String requestContext) {
687 Pattern pattern = Pattern.compile("v[0-9]+");
688 Matcher m = pattern.matcher(requestContext);
692 return new SchemaVersion(requestContext);
699 * @param vertices the vertices
701 * @param depth the depth
702 * @param cleanUp the clean up
703 * @return the introspector
704 * @throws AAIException the AAI exception
705 * @throws IllegalAccessException the illegal access exception
706 * @throws IllegalArgumentException the illegal argument exception
707 * @throws InvocationTargetException the invocation target exception
708 * @throws SecurityException the security exception
709 * @throws InstantiationException the instantiation exception
710 * @throws NoSuchMethodException the no such method exception
711 * @throws UnsupportedEncodingException the unsupported encoding exception
712 * @throws MalformedURLException the malformed URL exception
713 * @throws AAIUnknownObjectException
714 * @throws URISyntaxException
716 public Introspector dbToObject(List<Vertex> vertices, final Introspector obj, int depth, boolean nodeOnly, String cleanUp) throws UnsupportedEncodingException, AAIException {
717 final int internalDepth;
718 if (depth == Integer.MAX_VALUE) {
719 internalDepth = depth--;
721 internalDepth = depth;
723 StopWatch.conditionalStart();
724 if (vertices.size() > 1 && !obj.isContainer()) {
725 dbTimeMsecs += StopWatch.stopIfStarted();
726 throw new AAIException("AAI_6136", "query object mismatch: this object cannot hold multiple items." + obj.getDbName());
727 } else if (obj.isContainer()) {
729 String listProperty = null;
730 for (String property : obj.getProperties()) {
731 if (obj.isListType(property) && obj.isComplexGenericType(property)) {
732 listProperty = property;
736 final String propertyName = listProperty;
737 getList = (List) obj.getValue(listProperty);
739 /* This is an experimental multithreading experiment
742 ExecutorService pool = GetAllPool.getInstance().getPool();
744 List<Future<Object>> futures = new ArrayList<>();
746 QueryEngine tgEngine = this.engine.getQueryEngine();
747 for (Vertex v : vertices) {
749 AaiCallable<Object> task = new AaiCallable<Object>() {
751 public Object process() throws UnsupportedEncodingException, AAIException {
752 Set<Vertex> seen = new HashSet<>();
753 Introspector childObject;
755 childObject = obj.newIntrospectorInstanceOfNestedProperty(propertyName);
756 } catch (AAIUnknownObjectException e) {
760 dbToObject(childObject, v, seen, internalDepth, nodeOnly, cleanUp);
761 } catch (UnsupportedEncodingException e) {
763 } catch (AAIException e) {
766 return childObject.getUnderlyingObject();
767 //getList.add(childObject.getUnderlyingObject());
770 futures.add(pool.submit(task));
773 for (Future<Object> future : futures) {
775 getList.add(future.get());
776 } catch (ExecutionException e) {
777 dbTimeMsecs += StopWatch.stopIfStarted();
778 throw new AAIException("AAI_4000", e);
779 } catch (InterruptedException e) {
780 dbTimeMsecs += StopWatch.stopIfStarted();
781 throw new AAIException("AAI_4000", e);
784 } else if (vertices.size() == 1) {
785 Set<Vertex> seen = new HashSet<>();
786 dbToObject(obj, vertices.get(0), seen, depth, nodeOnly, cleanUp);
791 dbTimeMsecs += StopWatch.stopIfStarted();
800 * @param seen the seen
801 * @param depth the depth
802 * @param cleanUp the clean up
803 * @return the introspector
804 * @throws IllegalAccessException the illegal access exception
805 * @throws IllegalArgumentException the illegal argument exception
806 * @throws InvocationTargetException the invocation target exception
807 * @throws SecurityException the security exception
808 * @throws InstantiationException the instantiation exception
809 * @throws NoSuchMethodException the no such method exception
810 * @throws UnsupportedEncodingException the unsupported encoding exception
811 * @throws AAIException the AAI exception
812 * @throws MalformedURLException the malformed URL exception
813 * @throws AAIUnknownObjectException
814 * @throws URISyntaxException
816 private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, String cleanUp) throws AAIException, UnsupportedEncodingException {
824 boolean modified = false;
825 for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
826 List<Object> getList = null;
827 Vertex[] vertices = null;
829 if (!(obj.isComplexType(property) || obj.isListType(property))) {
830 this.copySimpleProperty(property, obj, v);
833 if (obj.isComplexType(property)) {
836 if (!property.equals("relationship-list") && depth >= 0) {
837 Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
838 Object result = dbToObject(argumentObject, v, seen, depth + 1, nodeOnly, cleanUp);
839 if (result != null) {
840 obj.setValue(property, argumentObject.getUnderlyingObject());
843 } else if (property.equals("relationship-list") && !nodeOnly) {
844 /* relationships need to be handled correctly */
845 Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
846 relationshipList = createRelationshipList(v, relationshipList, cleanUp);
847 if (relationshipList != null) {
849 obj.setValue(property, relationshipList.getUnderlyingObject());
854 } else if (obj.isListType(property)) {
856 if (property.equals("any")) {
859 String genericType = obj.getGenericTypeClass(property).getSimpleName();
860 if (obj.isComplexGenericType(property) && depth >= 0) {
861 final String childDbName = convertFromCamelCase(genericType);
862 String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
866 rule = edgeRules.getRule(new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build());
867 } catch (EdgeRuleNotFoundException e) {
868 throw new NoEdgeRuleFoundException(e);
869 } catch (AmbiguousRuleChoiceException e) {
870 throw new MultipleEdgeRuleFoundException(e);
872 if (!rule.getContains().equals(AAIDirection.NONE.toString())) {
873 //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
874 Direction ruleDirection = rule.getDirection();
875 Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
876 List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr);
877 itr = verticesList.stream().filter(item -> {
878 return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
881 getList = (List<Object>) obj.getValue(property);
885 while (itr.hasNext()) {
886 Vertex childVertex = itr.next();
887 if (!seen.contains(childVertex)) {
888 Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
890 Object result = dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp);
891 if (result != null) {
892 getList.add(argumentObject.getUnderlyingObject());
898 LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
901 if (processed == 0) {
902 //vertices were all seen, reset the list
909 } else if (obj.isSimpleGenericType(property)) {
910 List<Object> temp = this.engine.getListProperty(v, property);
912 getList = (List<Object>) obj.getValue(property);
913 getList.addAll(temp);
924 //no changes were made to this obj, discard the instance
928 this.enrichData(obj, v);
934 public Introspector getVertexProperties(Vertex v) throws AAIException, UnsupportedEncodingException {
935 String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
936 if (nodeType == null) {
937 throw new AAIException("AAI_6143");
940 Introspector obj = this.latestLoader.introspectorFromName(nodeType);
941 Set<Vertex> seen = new HashSet<>();
943 String cleanUp = "false";
944 boolean nodeOnly = true;
945 StopWatch.conditionalStart();
946 this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp);
947 dbTimeMsecs += StopWatch.stopIfStarted();
952 public Introspector getLatestVersionView(Vertex v) throws AAIException, UnsupportedEncodingException {
953 String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
954 if (nodeType == null) {
955 throw new AAIException("AAI_6143");
957 Introspector obj = this.latestLoader.introspectorFromName(nodeType);
958 Set<Vertex> seen = new HashSet<>();
959 int depth = AAIProperties.MAXIMUM_DEPTH;
960 String cleanUp = "false";
961 boolean nodeOnly = false;
962 StopWatch.conditionalStart();
963 this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp);
964 dbTimeMsecs += StopWatch.stopIfStarted();
969 * Copy simple property.
971 * @param property the property
974 * @throws InstantiationException the instantiation exception
975 * @throws IllegalAccessException the illegal access exception
976 * @throws IllegalArgumentException the illegal argument exception
977 * @throws InvocationTargetException the invocation target exception
978 * @throws NoSuchMethodException the no such method exception
979 * @throws SecurityException the security exception
981 private void copySimpleProperty(String property, Introspector obj, Vertex v) {
982 final Object temp = getProperty(obj, property, v);
984 obj.setValue(property, temp);
990 * Load the introspector from the hashmap for the given property key
992 * @param property - vertex property
993 * @param obj - introspector object representing the vertex
994 * @param hashMap - Containing a list of pre-fetched properties for a given vertex
996 private void copySimplePropertyFromHashMap(String property, Introspector obj, Map<String, Object> hashMap){
998 final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
999 String dbPropertyName = property;
1001 if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
1002 dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS);
1005 final Object temp = hashMap.getOrDefault(dbPropertyName, null);
1008 obj.setValue(property, temp);
1013 * Simple db to object.
1015 * @param obj the obj
1017 * @throws InstantiationException the instantiation exception
1018 * @throws IllegalAccessException the illegal access exception
1019 * @throws IllegalArgumentException the illegal argument exception
1020 * @throws InvocationTargetException the invocation target exception
1021 * @throws NoSuchMethodException the no such method exception
1022 * @throws SecurityException the security exception
1024 private void simpleDbToObject(Introspector obj, Vertex v) {
1025 for(String key : obj.getProperties()){
1026 this.copySimpleProperty(key, obj, v);
1031 public Map<String, Object> convertVertexToHashMap(Introspector obj, Vertex v){
1033 long startTime = System.currentTimeMillis();
1035 Set<String> simpleProperties = obj.getSimpleProperties(PropertyPredicates.isVisible());
1036 String[] simplePropsArray = new String[simpleProperties.size()];
1037 simplePropsArray = simpleProperties.toArray(simplePropsArray);
1039 Map<String, Object> simplePropsHashMap = new HashMap<>(simplePropsArray.length * 2);
1041 v.properties(simplePropsArray).forEachRemaining((vp) -> simplePropsHashMap.put(vp.key(), vp.value()));
1043 return simplePropsHashMap;
1046 public Introspector dbToRelationshipObject(Vertex v) throws UnsupportedEncodingException, AAIException {
1047 Introspector relationshipList = this.latestLoader.introspectorFromName("relationship-list");
1048 relationshipList = createRelationshipList(v, relationshipList, "false");
1049 return relationshipList;
1052 * Creates the relationship list.
1055 * @param obj the obj
1056 * @param cleanUp the clean up
1057 * @return the object
1058 * @throws InstantiationException the instantiation exception
1059 * @throws IllegalAccessException the illegal access exception
1060 * @throws IllegalArgumentException the illegal argument exception
1061 * @throws InvocationTargetException the invocation target exception
1062 * @throws NoSuchMethodException the no such method exception
1063 * @throws SecurityException the security exception
1064 * @throws UnsupportedEncodingException the unsupported encoding exception
1065 * @throws AAIException the AAI exception
1066 * @throws MalformedURLException the malformed URL exception
1067 * @throws URISyntaxException
1069 private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp) throws UnsupportedEncodingException, AAIException {
1071 String[] cousinRules = new String[0];
1074 cousinRules = edgeRules.retrieveCachedCousinLabels(obj.getDbName());
1075 } catch (ExecutionException e) {
1076 LOGGER.warn("Encountered an execution exception while retrieving labels for the node type {} using cached", obj.getDbName(), e);
1079 List<Vertex> cousins = null;
1080 if(cousinRules != null && cousinRules.length != 0){
1081 cousins = this.engine.getQueryEngine().findCousinVertices(v, cousinRules);
1083 cousins = this.engine.getQueryEngine().findCousinVertices(v);
1086 List<Object> relationshipObjList = obj.getValue("relationship");
1087 VertexProperty nodeTypeProperty = v.property(AAIProperties.NODE_TYPE);
1089 if(!nodeTypeProperty.isPresent()){
1090 LoggingContext.responseDescription(MISSING_REQUIRED_NODE_PROPERTY);
1091 LOGGER.warn("Not processing the vertex {} because its missing required property aai-node-type", v.id());
1092 LoggingContext.remove(LoggingContext.LoggingField.RESPONSE_DESCRIPTION.toString());
1096 String aNodeType = nodeTypeProperty.value().toString();
1098 TypeAlphabetizer alphabetizer = new TypeAlphabetizer();
1100 EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class);
1101 Set<String> keysWithMultipleLabels = edgeIngestor.getMultipleLabelKeys();
1103 // For the given vertex, find all the cousins
1104 // For each cousin retrieve the node type and then
1105 // check if the version is greater than the edge label version
1106 // meaning is the current version equal to greater than the version
1107 // where we introduced the edge labels into the relationship payload
1108 // If it is, then we check if the edge key there are multiple labels
1109 // If there are multiple labels, then we need to go to the database
1110 // to retrieve the labels between itself and cousin vertex
1111 // If there is only single label between the edge a and b, then
1112 // we can retrieve what that is without going to the database
1113 // from using the edge rules json and get the edge rule out of it
1114 EdgeRuleQuery.Builder queryBuilder = new EdgeRuleQuery.Builder(aNodeType);
1115 for (Vertex cousin : cousins) {
1116 VertexProperty vertexProperty = cousin.property(AAIProperties.NODE_TYPE);
1117 String bNodeType = null;
1118 if(vertexProperty.isPresent()){
1119 bNodeType = cousin.property(AAIProperties.NODE_TYPE).value().toString();
1121 // If the vertex is missing the aai-node-type
1122 // Then its either a bad vertex or its in the process
1123 // of getting deleted so we should ignore these vertexes
1124 LoggingContext.responseDescription(MISSING_REQUIRED_NODE_PROPERTY);
1125 if(LOGGER.isDebugEnabled()){
1126 LOGGER.debug("For the vertex {}, unable to retrieve the aai-node-type", v.id().toString());
1128 LOGGER.info("Unable to retrieve the aai-node-type for vertex, for more info enable debug log");
1130 LoggingContext.remove(LoggingContext.LoggingField.RESPONSE_DESCRIPTION.toString());
1133 if (obj.getVersion().compareTo(schemaVersions.getEdgeLabelVersion()) >= 0) {
1134 String edgeKey = alphabetizer.buildAlphabetizedKey(aNodeType, bNodeType);
1135 if(keysWithMultipleLabels.contains(edgeKey)){
1136 List<String> edgeLabels = this.getEdgeLabelsBetween(EdgeType.COUSIN, v, cousin);
1137 for(String edgeLabel: edgeLabels){
1138 Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
1139 Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, edgeLabel);
1140 if (result != null) {
1141 relationshipObjList.add(result);
1146 EdgeRule edgeRule = null;
1148 // Create a query based on the a nodetype and b nodetype
1149 // which is also a cousin edge and ensure the version
1150 // is used properly so for example in order to be backwards
1151 // compatible if we had allowed a edge between a and b
1152 // in a previous release and we decided to remove it from
1153 // the edge rules in the future we can display the edge
1154 // only for the older apis and the new apis if the edge rule
1155 // is removed will not be seen in the newer version of the API
1157 EdgeRuleQuery ruleQuery = queryBuilder
1159 .edgeType(EdgeType.COUSIN)
1160 .version(obj.getVersion())
1164 edgeRule = edgeIngestor.getRule(ruleQuery);
1165 } catch (EdgeRuleNotFoundException e) {
1166 LOGGER.warn("Caught an edge rule not found exception for query {}, {}," +
1167 " it could be the edge rule is no longer valid for the existing edge in db",
1168 ruleQuery, LogFormatTools.getStackTop(e));
1170 } catch (AmbiguousRuleChoiceException e) {
1171 LOGGER.error("Caught an ambiguous rule not found exception for query {}, {}",
1172 ruleQuery, LogFormatTools.getStackTop(e));
1176 Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
1177 Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp,edgeRule.getLabel());
1178 if (result != null) {
1179 relationshipObjList.add(result);
1183 Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
1184 Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
1185 if (result != null) {
1186 relationshipObjList.add(result);
1192 if (relationshipObjList.isEmpty()) {
1200 * Process edge relationship.
1202 * @param relationshipObj the relationship obj
1203 * @param edge the edge
1204 * @param cleanUp the clean up
1205 * @return the object
1206 * @throws InstantiationException the instantiation exception
1207 * @throws IllegalAccessException the illegal access exception
1208 * @throws IllegalArgumentException the illegal argument exception
1209 * @throws InvocationTargetException the invocation target exception
1210 * @throws NoSuchMethodException the no such method exception
1211 * @throws SecurityException the security exception
1212 * @throws UnsupportedEncodingException the unsupported encoding exception
1213 * @throws AAIException the AAI exception
1214 * @throws MalformedURLException the malformed URL exception
1215 * @throws AAIUnknownObjectException
1216 * @throws URISyntaxException
1218 private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp, String edgeLabel) throws UnsupportedEncodingException, AAIUnknownObjectException {
1220 VertexProperty aaiUriProperty = cousin.property("aai-uri");
1222 if(!aaiUriProperty.isPresent()){
1226 URI uri = UriBuilder.fromUri(aaiUriProperty.value().toString()).build();
1228 URIToRelationshipObject uriParser = null;
1229 Introspector result = null;
1231 uriParser = new URIToRelationshipObject(relationshipObj.getLoader(), uri, this.baseURL);
1232 result = uriParser.getResult();
1233 } catch (AAIException | URISyntaxException e) {
1234 LOGGER.error("Error while processing edge relationship in version " + relationshipObj.getVersion() + " (bad vertex ID=" + ": "
1235 + e.getMessage() + " " + LogFormatTools.getStackTop(e));
1239 VertexProperty cousinVertexNodeType = cousin.property(AAIProperties.NODE_TYPE);
1241 if(cousinVertexNodeType.isPresent()){
1242 String cousinType = cousinVertexNodeType.value().toString();
1243 if(namedPropNodes.contains(cousinType)){
1244 this.addRelatedToProperty(result, cousin, cousinType);
1248 if (edgeLabel != null && result.hasProperty("relationship-label")) {
1249 result.setValue("relationship-label", edgeLabel);
1252 return result.getUnderlyingObject();
1256 * Gets the URI for vertex.
1259 * @return the URI for vertex
1260 * @throws InstantiationException the instantiation exception
1261 * @throws IllegalAccessException the illegal access exception
1262 * @throws IllegalArgumentException the illegal argument exception
1263 * @throws InvocationTargetException the invocation target exception
1264 * @throws NoSuchMethodException the no such method exception
1265 * @throws SecurityException the security exception
1266 * @throws UnsupportedEncodingException the unsupported encoding exception
1267 * @throws AAIUnknownObjectException
1269 public URI getURIForVertex(Vertex v) throws UnsupportedEncodingException {
1271 return getURIForVertex(v, false);
1274 public URI getURIForVertex(Vertex v, boolean overwrite) throws UnsupportedEncodingException {
1275 URI uri = UriBuilder.fromPath("/unknown-uri").build();
1277 String aaiUri = v.<String>property(AAIProperties.AAI_URI).orElse(null);
1279 if (aaiUri != null && !overwrite) {
1280 uri = UriBuilder.fromPath(aaiUri).build();
1287 * Gets the URI from list.
1289 * @param list the list
1290 * @return the URI from list
1291 * @throws UnsupportedEncodingException the unsupported encoding exception
1293 private URI getURIFromList(List<Introspector> list) throws UnsupportedEncodingException {
1295 StringBuilder sb = new StringBuilder();
1296 for (Introspector i : list) {
1297 sb.insert(0, i.getURI());
1300 uri = sb.toString();
1301 return UriBuilder.fromPath(uri).build();
1304 public void addRelatedToProperty(Introspector relationship, Vertex cousinVertex, String cousinType) throws AAIUnknownObjectException {
1306 Introspector obj = null;
1309 obj = this.loader.introspectorFromName(cousinType);
1310 } catch(AAIUnknownObjectException ex){
1311 if(LOGGER.isTraceEnabled()){
1312 LOGGER.trace("Encountered unknown object exception when trying to load nodetype of {} for vertex id {}", cousinType, cousinVertex.id());
1317 String nameProps = obj.getMetadata(ObjectMetadata.NAME_PROPS);
1318 List<Introspector> relatedToProperties = new ArrayList<>();
1320 if (nameProps != null) {
1321 String[] props = nameProps.split(",");
1322 for (String prop : props) {
1323 final Object temp = getProperty(obj, prop, cousinVertex);
1324 Introspector relatedTo = relationship.newIntrospectorInstanceOfNestedProperty("related-to-property");
1325 relatedTo.setValue("property-key", cousinType + "." + prop);
1326 relatedTo.setValue("property-value", temp);
1327 relatedToProperties.add(relatedTo);
1331 if (!relatedToProperties.isEmpty()) {
1332 List relatedToList = (List) relationship.getValue("related-to-property");
1333 for (Introspector introspector : relatedToProperties) {
1334 relatedToList.add(introspector.getUnderlyingObject());
1340 private Object getProperty(Introspector obj, String prop, Vertex vertex){
1342 final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(prop);
1343 String dbPropertyName = prop;
1345 if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
1346 dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS);
1349 return vertex.<Object>property(dbPropertyName).orElse(null);
1355 * @param relationship the relationship
1356 * @param inputVertex the input vertex
1357 * @return true, if successful
1358 * @throws UnsupportedEncodingException the unsupported encoding exception
1359 * @throws AAIException the AAI exception
1361 public boolean createEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
1363 Vertex relatedVertex = null;
1364 StopWatch.conditionalStart();
1365 QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
1367 String label = null;
1368 if (relationship.hasProperty("relationship-label")) {
1369 label = relationship.getValue("relationship-label");
1372 List<Vertex> results = parser.getQueryBuilder().toList();
1373 if (results.isEmpty()) {
1374 dbTimeMsecs += StopWatch.stopIfStarted();
1375 AAIException e = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
1376 e.getTemplateVars().add(parser.getResultType());
1377 e.getTemplateVars().add(parser.getUri().toString());
1380 //still an issue if there's more than one
1381 relatedVertex = results.get(0);
1384 if (relatedVertex != null) {
1388 e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
1390 edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label);
1392 //attempted to link two vertexes already linked
1395 dbTimeMsecs += StopWatch.stopIfStarted();
1399 dbTimeMsecs += StopWatch.stopIfStarted();
1404 * Gets all the edges between of the type with the specified label.
1406 * @param aVertex the out vertex
1407 * @param bVertex the in vertex
1408 * @return the edges between
1409 * @throws AAIException the AAI exception
1410 * @throws NoEdgeRuleFoundException
1412 private Edge getEdgeBetweenWithLabel(EdgeType type, Vertex aVertex, Vertex bVertex, EdgeRule edgeRule) {
1416 if (bVertex != null) {
1417 GraphTraversal<Vertex, Edge> findEdgesBetween = null;
1418 if (EdgeType.TREE.equals(type)) {
1419 GraphTraversal<Vertex,Vertex> findVertex = this.engine.asAdmin().getTraversalSource().V(bVertex);
1420 if(edgeRule.getDirection().equals(Direction.IN)){
1421 findEdgesBetween = findVertex.outE(edgeRule.getLabel())
1422 .has(EdgeProperty.CONTAINS.toString(), edgeRule.getContains())
1424 __.has(EdgeField.PRIVATE.toString(), true)
1427 findEdgesBetween = findVertex.inE(edgeRule.getLabel())
1428 .has(EdgeProperty.CONTAINS.toString(), edgeRule.getContains())
1430 __.has(EdgeField.PRIVATE.toString(), true)
1433 findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(aVertex.id())).limit(1);
1435 findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE(edgeRule.getLabel());
1436 findEdgesBetween = findEdgesBetween
1437 .has(EdgeProperty.CONTAINS.toString(), "NONE")
1439 __.has(EdgeField.PRIVATE.toString(), true)
1441 findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id())).limit(1);
1443 List<Edge> list = findEdgesBetween.toList();
1444 if(!list.isEmpty()){
1445 result = list.get(0);
1453 * Gets all the edges between of the type.
1455 * @param aVertex the out vertex
1456 * @param bVertex the in vertex
1457 * @return the edges between
1458 * @throws AAIException the AAI exception
1459 * @throws NoEdgeRuleFoundException
1461 private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
1463 List<Edge> result = new ArrayList<>();
1465 if (bVertex != null) {
1466 GraphTraversal<Vertex, Edge> findEdgesBetween = null;
1467 findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
1468 if (EdgeType.TREE.equals(type)) {
1469 findEdgesBetween = findEdgesBetween
1472 __.has(EdgeProperty.CONTAINS.toString(), "NONE"),
1473 __.has(EdgeField.PRIVATE.toString(), true)
1477 findEdgesBetween = findEdgesBetween
1478 .has(EdgeProperty.CONTAINS.toString(), "NONE")
1480 __.has(EdgeField.PRIVATE.toString(), true)
1483 findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
1484 result = findEdgesBetween.toList();
1491 * Gets all the edges string between of the type.
1493 * @param aVertex the out vertex
1494 * @param bVertex the in vertex
1495 * @return the edges between
1496 * @throws AAIException the AAI exception
1497 * @throws NoEdgeRuleFoundException
1499 private List<String> getEdgeLabelsBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
1501 List<String> result = new ArrayList<>();
1503 if (bVertex != null) {
1504 GraphTraversal<Vertex, Edge> findEdgesBetween = null;
1505 findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
1506 if (EdgeType.TREE.equals(type)) {
1507 findEdgesBetween = findEdgesBetween
1510 __.has(EdgeProperty.CONTAINS.toString(), "NONE"),
1511 __.has(EdgeField.PRIVATE.toString(), true)
1515 findEdgesBetween = findEdgesBetween
1516 .has(EdgeProperty.CONTAINS.toString(), "NONE")
1518 __.has(EdgeField.PRIVATE.toString(), true)
1521 findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
1522 result = findEdgesBetween.label().toList();
1528 * Gets all the edges string between of the type.
1530 * @param aVertex the out vertex
1531 * @param bVertex the in vertex
1532 * @return the edges between
1533 * @throws AAIException the AAI exception
1534 * @throws NoEdgeRuleFoundException
1536 private Long getEdgeLabelsCount(Vertex aVertex, Vertex bVertex) {
1540 if (bVertex != null) {
1541 GraphTraversal<Vertex, Edge> findEdgesBetween = null;
1542 findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
1543 findEdgesBetween = findEdgesBetween
1544 .has(EdgeProperty.CONTAINS.toString(), "NONE")
1546 __.has(EdgeField.PRIVATE.toString(), true)
1548 findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
1549 result = findEdgesBetween.count().next();
1554 * Gets all the edges between the vertexes with the label and type.
1556 * @param aVertex the out vertex
1557 * @param bVertex the in vertex
1559 * @return the edges between
1560 * @throws AAIException the AAI exception
1562 private Edge getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
1566 if (bVertex != null) {
1567 String aType = aVertex.<String>property(AAIProperties.NODE_TYPE).value();
1568 String bType = bVertex.<String>property(AAIProperties.NODE_TYPE).value();
1569 EdgeRuleQuery q = new EdgeRuleQuery.Builder(aType, bType).edgeType(type).label(label).build();
1572 rule = edgeRules.getRule(q);
1573 } catch (EdgeRuleNotFoundException e) {
1574 throw new NoEdgeRuleFoundException(e);
1575 } catch (AmbiguousRuleChoiceException e) {
1576 throw new MultipleEdgeRuleFoundException(e);
1578 edge = this.getEdgeBetweenWithLabel(type, aVertex, bVertex, rule);
1585 * Gets the edge between with the label and edge type.
1587 * @param aVertex the out vertex
1588 * @param bVertex the in vertex
1590 * @return the edge between
1591 * @throws AAIException the AAI exception
1592 * @throws NoEdgeRuleFoundException
1594 public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
1596 StopWatch.conditionalStart();
1597 if (bVertex != null) {
1599 Edge edge = this.getEdgesBetween(type, aVertex, bVertex, label);
1601 dbTimeMsecs += StopWatch.stopIfStarted();
1606 dbTimeMsecs += StopWatch.stopIfStarted();
1610 public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
1611 return this.getEdgeBetween(type, aVertex, bVertex, null);
1618 * @param relationship the relationship
1619 * @param inputVertex the input vertex
1620 * @return true, if successful
1621 * @throws UnsupportedEncodingException the unsupported encoding exception
1622 * @throws AAIException the AAI exception
1624 public boolean deleteEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
1626 Vertex relatedVertex = null;
1627 StopWatch.conditionalStart();
1628 QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
1630 List<Vertex> results = parser.getQueryBuilder().toList();
1632 String label = null;
1633 if (relationship.hasProperty("relationship-label")) {
1634 label = relationship.getValue("relationship-label");
1637 if (results.isEmpty()) {
1638 dbTimeMsecs += StopWatch.stopIfStarted();
1642 relatedVertex = results.get(0);
1645 edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
1646 } catch (NoEdgeRuleFoundException e) {
1647 dbTimeMsecs += StopWatch.stopIfStarted();
1648 throw new AAIException("AAI_6129", e);
1652 dbTimeMsecs += StopWatch.stopIfStarted();
1655 dbTimeMsecs += StopWatch.stopIfStarted();
1662 * Delete items with traversal.
1664 * @param vertexes the vertexes
1665 * @throws IllegalStateException the illegal state exception
1667 public void deleteItemsWithTraversal(List<Vertex> vertexes) throws IllegalStateException {
1669 for (Vertex v : vertexes) {
1670 deleteWithTraversal(v);
1676 * Delete with traversal.
1678 * @param startVertex the start vertex
1680 public void deleteWithTraversal(Vertex startVertex) {
1681 StopWatch.conditionalStart();
1682 List<Vertex> results = this.engine.getQueryEngine().findDeletable(startVertex);
1684 for (Vertex v : results) {
1685 LOGGER.debug("Removing vertex {} with label {}", v.id(), v.label());
1688 dbTimeMsecs += StopWatch.stopIfStarted();
1692 * Removes the list of vertexes from the graph
1694 * Current the vertex label will just be vertex but
1695 * in the future the aai-node-type property will be replaced
1696 * by using the vertex label as when retrieving an vertex
1697 * and retrieving an single property on an vertex will pre-fetch
1698 * all the properties of that vertex and this is due to the following property
1701 * query.fast-property=true
1704 * JanusGraph doesn't provide the capability to override that
1705 * at a transaction level and there is a plan to move to vertex label
1706 * so it is best to utilize this for now and when the change is applied
1708 * @param vertices - list of vertices to delete from the graph
1710 void delete(List<Vertex> vertices){
1711 StopWatch.conditionalStart();
1713 for (Vertex v : vertices) {
1714 LOGGER.debug("Removing vertex {} with label {}", v.id(), v.label());
1718 dbTimeMsecs += StopWatch.stopIfStarted();
1725 * @param resourceVersion the resource version
1726 * @throws IllegalArgumentException the illegal argument exception
1727 * @throws AAIException the AAI exception
1728 * @throws InterruptedException the interrupted exception
1730 public void delete(Vertex v, List<Vertex> deletableVertices, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
1732 boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
1734 * The reason why I want to call PreventDeleteSemantics second time is to catch the prevent-deletes in a chain
1735 * These are far-fewer than seeing a prevnt-delete on the vertex to be deleted
1736 * So its better to make these in 2 steps
1738 if (result && !deletableVertices.isEmpty()) {
1739 result = verifyPreventDeleteSemantics(deletableVertices);
1744 deleteWithTraversal(v);
1745 } catch (IllegalStateException e) {
1746 throw new AAIException("AAI_6110", e);
1758 * @param resourceVersion the resource version
1759 * @throws IllegalArgumentException the illegal argument exception
1760 * @throws AAIException the AAI exception
1761 * @throws InterruptedException the interrupted exception
1763 public void delete(Vertex v, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
1765 boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
1770 deleteWithTraversal(v);
1771 } catch (IllegalStateException e) {
1772 throw new AAIException("AAI_6110", e);
1780 * Verify delete semantics.
1782 * @param vertex the vertex
1783 * @param resourceVersion the resource version
1784 * @return true, if successful
1785 * @throws AAIException the AAI exception
1787 private boolean verifyDeleteSemantics(Vertex vertex, String resourceVersion, boolean enableResourceVersion) throws AAIException {
1788 boolean result = true;
1789 String nodeType = "";
1790 String errorDetail = " unknown delete semantic found";
1791 String aaiExceptionCode = "";
1792 nodeType = vertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
1793 if (enableResourceVersion && !this.verifyResourceVersion("delete", nodeType, vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) {
1795 List<Vertex> vertices = new ArrayList<Vertex>();
1796 vertices.add(vertex);
1797 result = verifyPreventDeleteSemantics(vertices);
1803 * Verify Prevent delete semantics.
1805 * @param vertices the list of vertices
1806 * @return true, if successful
1807 * @throws AAIException the AAI exception
1809 private boolean verifyPreventDeleteSemantics(List<Vertex> vertices) throws AAIException {
1810 boolean result = true;
1811 String nodeType = "";
1812 String errorDetail = " unknown delete semantic found";
1813 String aaiExceptionCode = "";
1815 StopWatch.conditionalStart();
1817 * This takes in all the vertices in a cascade-delete-chain and checks if there is any edge with a "prevent-delete" condition
1818 * If yes - that should prevent the deletion of the vertex
1819 * Dedup makes sure we dont capture the prevent-delete vertices twice
1820 * The prevent-delete vertices are stored so that the error message displays what prevents the delete
1823 List<Object> preventDeleteVertices = this.engine.asAdmin().getReadOnlyTraversalSource().V(vertices).
1824 union(__.inE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.IN.toString()).outV().values(AAIProperties.NODE_TYPE),
1825 __.outE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.OUT.toString()).inV().values(AAIProperties.NODE_TYPE))
1828 dbTimeMsecs += StopWatch.stopIfStarted();
1829 if (!preventDeleteVertices.isEmpty()) {
1830 aaiExceptionCode = "AAI_6110";
1831 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);
1835 throw new AAIException(aaiExceptionCode, errorDetail);
1841 * Verify resource version.
1843 * @param action the action
1844 * @param nodeType the node type
1845 * @param currentResourceVersion the current resource version
1846 * @param resourceVersion the resource version
1847 * @param uri the uri
1848 * @return true, if successful
1849 * @throws AAIException the AAI exception
1851 public boolean verifyResourceVersion(String action, String nodeType, String currentResourceVersion, String resourceVersion, String uri) throws AAIException {
1852 String enabled = "";
1853 String errorDetail = "";
1854 String aaiExceptionCode = "";
1855 boolean isDeleteResourceVersionOk = true;
1856 if (currentResourceVersion == null) {
1857 currentResourceVersion = "";
1860 if (resourceVersion == null) {
1861 resourceVersion = "";
1864 enabled = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
1866 } catch (AAIException e) {
1867 ErrorLogHelper.logException(e);
1869 if (enabled.equals("true")) {
1870 if ("delete".equals(action)) {
1871 isDeleteResourceVersionOk = verifyResourceVersionForDelete(currentResourceVersion, resourceVersion);
1873 if ((!isDeleteResourceVersionOk) || ((!"delete".equals(action)) && (!currentResourceVersion.equals(resourceVersion)))) {
1874 if ("create".equals(action) && !resourceVersion.equals("")) {
1875 errorDetail = "resource-version passed for " + action + " of " + uri;
1876 aaiExceptionCode = "AAI_6135";
1877 } else if (resourceVersion.equals("")) {
1878 errorDetail = "resource-version not passed for " + action + " of " + uri;
1879 aaiExceptionCode = "AAI_6130";
1881 errorDetail = "resource-version MISMATCH for " + action + " of " + uri;
1882 aaiExceptionCode = "AAI_6131";
1885 throw new AAIException(aaiExceptionCode, errorDetail);
1893 * Verify resource version for delete.
1895 * @param currentResourceVersion the current resource version
1896 * @param resourceVersion the resource version
1897 * @return true, if successful or false if there is a mismatch
1899 private boolean verifyResourceVersionForDelete(String currentResourceVersion, String resourceVersion) {
1901 boolean isDeleteResourceVersionOk = true;
1902 String resourceVersionDisabledUuid = AAIConfig.get(AAIConstants.AAI_RESVERSION_DISABLED_UUID,
1903 AAIConstants.AAI_RESVERSION_DISABLED_UUID_DEFAULT);
1905 if ((!currentResourceVersion.equals(resourceVersion)) && (!resourceVersion.equals(resourceVersionDisabledUuid))) {
1906 isDeleteResourceVersionOk = false;
1908 return isDeleteResourceVersionOk;
1912 * Convert from camel case.
1914 * @param name the name
1915 * @return the string
1917 private String convertFromCamelCase(String name) {
1919 result = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, name);
1921 NamingExceptions exceptions = NamingExceptions.getInstance();
1922 result = exceptions.getDBName(result);
1927 private boolean canModify(Introspector obj, String propName, String requestContext) {
1928 final String readOnly = obj.getPropertyMetadata(propName).get(PropertyMetadata.READ_ONLY);
1929 if (readOnly != null) {
1930 final String[] items = readOnly.split(",");
1931 for (String item : items) {
1932 if (requestContext.equals(item)) {
1940 private void executePreSideEffects(Introspector obj, Vertex self) throws AAIException {
1942 SideEffectRunner runner = new SideEffectRunner
1943 .Builder(this.engine, this).addSideEffect(DataCopy.class).addSideEffect(PrivateEdge.class).build();
1945 runner.execute(obj, self);
1948 private void executePostSideEffects(Introspector obj, Vertex self) throws AAIException {
1950 SideEffectRunner runner = new SideEffectRunner
1951 .Builder(this.engine, this).addSideEffect(DataLinkWriter.class).build();
1953 runner.execute(obj, self);
1956 private void enrichData(Introspector obj, Vertex self) throws AAIException {
1958 SideEffectRunner runner = new SideEffectRunner
1959 .Builder(this.engine, this).addSideEffect(DataLinkReader.class).build();
1961 runner.execute(obj, self);
1964 public double getDBTimeMsecs() {
1965 return (dbTimeMsecs);
1969 * Db to object With Filters
1970 * This is for a one-time run with Tenant Isloation to only filter relationships
1971 * TODO: Chnage the original dbToObject to take filter parent/cousins
1973 * @param obj the obj
1974 * @param v the vertex from the graph
1975 * @param depth the depth
1976 * @param nodeOnly specify if to exclude relationships or not
1977 * @param filterCousinNodes
1978 * @return the introspector
1979 * @throws AAIException the AAI exception
1980 * @throws IllegalAccessException the illegal access exception
1981 * @throws IllegalArgumentException the illegal argument exception
1982 * @throws InvocationTargetException the invocation target exception
1983 * @throws SecurityException the security exception
1984 * @throws InstantiationException the instantiation exception
1985 * @throws NoSuchMethodException the no such method exception
1986 * @throws UnsupportedEncodingException the unsupported encoding exception
1987 * @throws MalformedURLException the malformed URL exception
1988 * @throws AAIUnknownObjectException
1989 * @throws URISyntaxException
1991 //TODO - See if you can merge the 2 dbToObjectWithFilters
1992 public Introspector dbToObjectWithFilters(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, List<String> filterCousinNodes, List<String> filterParentNodes) throws AAIException, UnsupportedEncodingException {
1993 String cleanUp = "false";
1999 boolean modified = false;
2000 for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
2001 List<Object> getList = null;
2002 Vertex[] vertices = null;
2004 if (!(obj.isComplexType(property) || obj.isListType(property))) {
2005 this.copySimpleProperty(property, obj, v);
2008 if (obj.isComplexType(property)) {
2009 /* container case */
2011 if (!property.equals("relationship-list") && depth >= 0) {
2012 Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
2013 Object result = dbToObjectWithFilters(argumentObject, v, seen, depth + 1, nodeOnly, filterCousinNodes, filterParentNodes);
2014 if (result != null) {
2015 obj.setValue(property, argumentObject.getUnderlyingObject());
2018 } else if (property.equals("relationship-list") && !nodeOnly) {
2019 /* relationships need to be handled correctly */
2020 Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
2021 relationshipList = createFilteredRelationshipList(v, relationshipList, cleanUp, filterCousinNodes);
2022 if (relationshipList != null) {
2024 obj.setValue(property, relationshipList.getUnderlyingObject());
2029 } else if (obj.isListType(property)) {
2031 if (property.equals("any")) {
2034 String genericType = obj.getGenericTypeClass(property).getSimpleName();
2035 if (obj.isComplexGenericType(property) && depth >= 0) {
2036 final String childDbName = convertFromCamelCase(genericType);
2037 String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2040 boolean isthisParentRequired = filterParentNodes.parallelStream().anyMatch(childDbName::contains);
2042 EdgeRuleQuery q = new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build();
2045 rule = edgeRules.getRule(q);
2046 } catch (EdgeRuleNotFoundException e) {
2047 throw new NoEdgeRuleFoundException(e);
2048 } catch (AmbiguousRuleChoiceException e) {
2049 throw new MultipleEdgeRuleFoundException(e);
2051 if (!rule.getContains().equals(AAIDirection.NONE.toString()) && isthisParentRequired) {
2052 //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
2053 Direction ruleDirection = rule.getDirection();
2054 Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
2055 List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr);
2056 itr = verticesList.stream().filter(item -> {
2057 return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
2059 if (itr.hasNext()) {
2060 getList = (List<Object>) obj.getValue(property);
2064 while (itr.hasNext()) {
2065 Vertex childVertex = itr.next();
2066 if (!seen.contains(childVertex)) {
2067 Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
2069 Object result = dbToObjectWithFilters(argumentObject, childVertex, seen, depth, nodeOnly, filterCousinNodes, filterParentNodes);
2070 if (result != null) {
2071 getList.add(argumentObject.getUnderlyingObject());
2077 LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
2080 if (processed == 0) {
2081 //vertices were all seen, reset the list
2084 if (processed > 0) {
2088 } else if (obj.isSimpleGenericType(property)) {
2089 List<Object> temp = this.engine.getListProperty(v, property);
2091 getList = (List<Object>) obj.getValue(property);
2092 getList.addAll(temp);
2103 //no changes were made to this obj, discard the instance
2107 this.enrichData(obj, v);
2113 * Creates the relationship list with the filtered node types.
2116 * @param obj the obj
2117 * @param cleanUp the clean up
2118 * @return the object
2119 * @throws InstantiationException the instantiation exception
2120 * @throws IllegalAccessException the illegal access exception
2121 * @throws IllegalArgumentException the illegal argument exception
2122 * @throws InvocationTargetException the invocation target exception
2123 * @throws NoSuchMethodException the no such method exception
2124 * @throws SecurityException the security exception
2125 * @throws UnsupportedEncodingException the unsupported encoding exception
2126 * @throws AAIException the AAI exception
2127 * @throws MalformedURLException the malformed URL exception
2128 * @throws URISyntaxException
2130 private Introspector createFilteredRelationshipList(Vertex v, Introspector obj, String cleanUp, List<String> filterNodes) throws UnsupportedEncodingException, AAIException {
2131 List<Vertex> allCousins = this.engine.getQueryEngine().findCousinVertices(v);
2133 Iterator<Vertex> cousinVertices = allCousins.stream().filter(item -> {
2134 String node = (String) item.property(AAIProperties.NODE_TYPE).orElse("");
2135 return filterNodes.parallelStream().anyMatch(node::contains);
2139 List<Vertex> cousins = (List<Vertex>) IteratorUtils.toList(cousinVertices);
2141 //items.parallelStream().anyMatch(inputStr::contains)
2142 List<Object> relationshipObjList = obj.getValue("relationship");
2143 for (Vertex cousin : cousins) {
2145 Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
2146 Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
2147 if (result != null) {
2148 relationshipObjList.add(result);
2154 if (relationshipObjList.isEmpty()) {