aboutsummaryrefslogtreecommitdiffstats
path: root/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java
diff options
context:
space:
mode:
Diffstat (limited to 'ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java')
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java3964
1 files changed, 3964 insertions, 0 deletions
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java
new file mode 100644
index 0000000..978cb57
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java
@@ -0,0 +1,3964 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.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.openecomp.aai.dbgen;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.google.common.net.InetAddresses;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanProperty;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+/**
+ * General Database-level Utility class. These methods deal with the database one dataNode / Edge at a time.
+ * Transactions are managed at a higher level by the calling classes by passing in a TitanTransaction object.
+ */
+public class DbMeth{
+
+ private static AAILogger aaiLogger = new AAILogger(DbMeth.class.getName());
+
+ /**
+ * Patch aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex patchAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "patchAaiNode");
+
+ // If they're calling patchAaiNode, then we only want to add/update the properties that they
+ // pass us in the propHash. If there are others already in the DB, we leave them alone.
+
+ // Note: to be really official, we'd throw an error if the node wasn't already in the db.
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = true;
+ Boolean patchOnly = true;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+
+ } // end of patchAaiNode()
+
+ /**
+ * Patch aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex patchAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal) throws AAIException{
+ return patchAaiNode( transId, fromAppId, graph, nodeType,
+ propHash, depNodeVal, null );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly, String apiVersion) throws AAIException{
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ return persistAaiNodeBASE( transId, fromAppId, graph, nodeType,
+ propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion) throws AAIException{
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ Boolean patchOnly = false;
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ return( tv );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal) throws AAIException{
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ Boolean patchOnly = false;
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, null, objectExists);
+ return( tv );
+ } // end of persistAaiNode()
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion, boolean[] objectExists) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNode");
+ Boolean patchOnly = false;
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, null);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @param thisNodeVertex the this node vertex
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion, boolean[] objectExists, TitanVertex thisNodeVertex) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNode");
+ Boolean patchOnly = false;
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, thisNodeVertex);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+ }
+
+ /**
+ * Persist aai node BASE.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNodeBASE(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly,
+ String apiVersion, boolean[] objectExists) throws AAIException{
+ return persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, null);
+ }
+
+ /**
+ * Persist aai node BASE.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @param thisNodeVertex the this node vertex
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNodeBASE(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly,
+ String apiVersion, boolean[] objectExists, TitanVertex thisNodeVertex) throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNodeBASE");
+ logline.add("patchOnly", patchOnly);
+
+ if( graph == null ){
+ String emsg = "null graph object passed to persistAaiNodeBASE()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ boolean useDepNode = false;
+ String resourceVersion = null;
+ if( propHash.containsKey("resource-version") ){
+ resourceVersion = (String)(propHash.get("resource-version"));
+ }
+ String aaiUniqueKeyVal = null;
+ if( propHash.containsKey("aai-unique-key") ){
+ // Note -- we are assuming that nobody is monkeying with this. The 16-07 first-pass theory
+ // is that the REST layer is always gonna generate this or pass it through.
+ aaiUniqueKeyVal = (String)(propHash.get("aai-unique-key"));
+ propHash.remove("aai-unique-key");
+ }
+
+ if( needsADepNode4Uniqueness(transId, fromAppId, nodeType, apiVersion) ){
+ // This kind of node needs a dependent node (for uniqueness)
+ if( depNodeVal == null ){
+ // They should have passed in the node that this one depends on
+ String emsg = "null dependentNode object passed to persistAaiNodeBASE() but " + nodeType + " requires one.\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else if( ! nodeTypeACanDependOnB(transId, fromAppId, nodeType, depNodeVal.<String>property("aai-node-type").orElse(null), apiVersion) ){
+ // They should have passed in the right type of node as the dependent node
+ String emsg = "dependentNode of type " + depNodeVal.<String>property("aai-node-type").orElse(null) + " passed to persistAaiNodeBASE() for nodeType" + nodeType + ".\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ useDepNode = true;
+ }
+ else {
+ depNodeVal = null;
+ }
+
+ // Note: as of 1607, we no longer validate property names since that's covered by the REST layer.
+ // Same goes for required fields (as of 1602)
+
+ // Special ip-address validation for ipAddr nodes only... This will go away when we go to YANG and
+ // do validations like this up at that layer.
+ if( nodeType.equals("ipaddress") ){
+ // Note - this will throw an exception if the ipAddress is using a bad format
+ ipAddressFormatOK( transId, fromAppId, (String)propHash.get("addr"), (String)propHash.get("version") );
+ }
+
+ // Use the key-fields/dependentNode to check if this is an add or an update
+ // We assume that all NodeTypes at least one key-property defined. A dependentNode is optional.
+ if( ! dbMaps.NodeKeyProps.containsKey(nodeType) ){
+ // Problem if no key Properties defined for this nodeType
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "No node-key-properties defined in dbMaps for nodeType = " + nodeType + " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ Boolean hasAltKey1 = false;
+ HashMap <String,Object>nodeAltKey1PropsHash = new HashMap<String,Object>();
+ Collection <String> altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion);
+ if( altKey1Props != null ){
+ Iterator <String> altKey1PropI = altKey1Props.iterator();
+ while( altKey1PropI.hasNext() ){
+ String propName = altKey1PropI.next();
+ // NOTE: alt-keys are not always required fields. If it is null or blank, we won't
+ // do alt-key checks on it.
+ Object value = propHash.get(propName);
+ if( value != null && !value.toString().equals("") ){
+ hasAltKey1 = true;
+ nodeAltKey1PropsHash.put(propName, value);
+ }
+ }
+ }
+ HashMap <String,Object>nodeKeyPropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+
+ Object value = propHash.get(propName);
+ nodeKeyPropsHash.put(propName, value);
+ }
+
+ // Check if this node is already in the database based on the Primary Key Info
+ TitanVertex existingVert = thisNodeVertex;
+ boolean foundTheNodeInDb = true;
+
+ if (existingVert == null) {
+ try {
+ existingVert = getUniqueNode( transId, fromAppId, graph, nodeType, nodeKeyPropsHash, depNodeVal, apiVersion );
+ }
+ catch (AAIException e) {
+ if (e.getErrorObject().getErrorCode().equals("6114")) {
+ foundTheNodeInDb = false;
+ }
+ else {
+ throw e;
+ }
+ }
+ }
+
+ // this is so the notification knows whether or not the operation was an UPDATE or a CREATe
+ objectExists[0] = foundTheNodeInDb;
+ if( foundTheNodeInDb ){
+ // A record was found in the DB using the PK.
+ if( needToDoResourceVerCheck(apiVersion, patchOnly) ){
+ // Need to check that they knew what they were updating
+ String existingResVer = existingVert.<String>property("resource-version").orElse(null);
+ if( resourceVersion == null || resourceVersion.equals("") ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6130");
+ String detail = "Resource-version not passed for update of = " + nodeType + ", " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6130", detail);
+ }
+ else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version " + resourceVersion + " MISMATCH WITH EXISTING " + existingResVer + " for update of = " + nodeType + ", " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6131", detail);
+ }
+ }
+
+ // Need to ensure that the Alternate key isn't changing to a value that points to a different existing node.
+ // It is ok if it points to nothing -- that would just be an update for this node. It's also ok if
+ // it points to this (existing) node - that just means that it wasn't being updated.
+ if( hasAltKey1 ){
+ try {
+ TitanVertex chkVert = getUniqueNode( transId, fromAppId, graph, nodeType, nodeAltKey1PropsHash, depNodeVal, apiVersion );
+ if( ! chkVert.id().toString().equals(existingVert.id().toString()) ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6117");
+ String detail = "In-Use AlternateKey value passed for update of nodeType = " + nodeType;
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+ catch (AAIException e) {
+ if(! e.getErrorObject().getErrorCode().equals("6114") ){
+ throw e;
+ }
+ }
+ }
+ }
+ else {
+ // Note not in the DB -- This will be an ADD of a new node
+ // a) make sure they didn't say they were just doing "patchOnly" which cannot be an ADD.
+ // b) if there is an alternate key, we need to make sure the AK isn't already in use by somebody else.
+ if( patchOnly ){
+ String depMsg = "";
+ if( useDepNode ){
+ depMsg = " plus dependent node. ";
+ }
+ String msg = "Patch Request, but no Node of type " + nodeType + " found for properties: [" + propHash + "] " + depMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( needToDoResourceVerCheck(apiVersion, patchOnly) && (resourceVersion != null) && !resourceVersion.equals("") ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version was passed in, but this is an ADD of a " + nodeType + ", with these params: " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6131", detail);
+ }
+ if( hasAltKey1 ){
+ try {
+ getUniqueNode( transId, fromAppId, graph, nodeType, nodeAltKey1PropsHash, depNodeVal, apiVersion );
+ // Since the Primary Key for this nodeType wasn't found in the DB yet, the fact that
+ // we are able to find a record (no "6114" exception thrown) using the Alternate-Key is an error.
+ // We can't create a new node that uses an AK that's already in use.
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6117");
+ String detail = "Conflicting Key and Alternate-Key values passed for add of nodeType = " + nodeType;
+ throw new AAIException("AAI_6117", detail);
+ }
+ catch (AAIException e) {
+ if(! e.getErrorObject().getErrorCode().equals("6114") ){
+ throw e;
+ }
+ }
+ }
+ }
+
+ // ------------- Done with checking. Do the add or update to the dB -----------------------
+
+ if( foundTheNodeInDb ){
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ // ----- This is an UPDATE ------
+
+
+ String existingSourceOfTruth = fromAppId; // default value if we can't get the old one
+ Object tmpOb = existingVert.<Object>property("source-of-truth").orElse(null);
+ if( tmpOb != null ){
+ existingSourceOfTruth = tmpOb.toString();
+ }
+ long existingCreateTs = unixTimeNow; // default value if we can't get the old one
+ tmpOb = existingVert.<Object>property("aai-created-ts").orElse(null);
+ if( tmpOb != null ){
+ existingCreateTs = (long) tmpOb;
+ }
+
+ String msg = "UPDATE vertex of type = [" + nodeType + "] ";
+ if( useDepNode ){
+ String depNType = depNodeVal.<String>property("aai-node-type").orElse(null);
+ HashMap <String, Object> depNodePropKeysHash = getNodeKeyPropHash(transId, fromAppId, graph, depNodeVal);
+ msg = "UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash +
+ "] which rides on dependent node: type = " + depNType + ", with key(s) = [" + depNodePropKeysHash + "].";
+ logline.add("msg", msg);
+ }
+ else {
+ msg = "UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash + "] (no dep. node).";
+ logline.add("msg", msg);
+ }
+ String removeList = "";
+ if( ! patchOnly ){
+ // They are updating an existing record, and they want us to "process all defined properties" (not just patch)
+ // So we will see if the node has any properties that were not passed-in. Those need to be removed.
+ Collection <String> propCol = dbMaps.NodeProps.get(nodeType);
+ Iterator <String> propIter = propCol.iterator();
+ while( propIter.hasNext() ){
+ String propName = propIter.next();
+ if( ! propHash.containsKey(propName) && !DbEdgeRules.ReservedPropNames.containsKey(propName)){
+ if( thisPropertyWasPutByNewerVersionOfCode(apiVersion, nodeType, propName) ){
+ // we must be using an older version of code here - but the property that
+ // has not been passed in this persist call is one that this older version of
+ // the database did not know about. So leave it alone.
+ }
+ else {
+ removeList = removeList + "," + propName;
+ existingVert.property(propName).remove();
+ }
+ }
+ }
+ }
+ if( !removeList.equals("") ){
+ String rmMsg = "Removed these props on update: [" + removeList + "]";
+ logline.add("removePropList", rmMsg);
+ }
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ // update the parameters that have been passed in (except the key-properties)
+ // taking away the key-property check. We will now allow this since
+ // the keys were used to identify this node, so they should be good and
+ // there are times when Titan resolves conflicts by only using the
+ // data set in an update - and was losing our key info...
+ // Similar to the change noted below.
+ //if( ! nodeKeyPropsHash.containsKey(entry.getKey()) ){
+ // existingVert.setProperty( entry.getKey(), entry.getValue() );
+ //}
+ if( ! entry.getKey().equals("resource-version") ){
+ boolean nonSingleCardinality = false;
+ boolean setSoNoDupes = false;
+ if( checkPropCardinality(entry.getKey(), "Set") ){
+ nonSingleCardinality = true;
+ setSoNoDupes = true;
+ }
+ else if( checkPropCardinality(entry.getKey(), "List") ){
+ nonSingleCardinality = true;
+ }
+
+ Iterator <Object> valIter = null;
+ if( nonSingleCardinality ){
+ String className = entry.getValue().getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ valIter = ((ArrayList)(entry.getValue())).iterator();
+ }
+ else if( className.equals("List") ){
+ valIter = ((List)(entry.getValue())).iterator();
+ }
+ else if( className.equals("Set") ){
+ valIter = ((Set)(entry.getValue())).iterator();
+ }
+ }
+
+ if( nonSingleCardinality ){
+ // This property has Cardinality of List or Set - which need to be handled carefully
+ // Note -- for Lists or Sets, we assume they are of dataType String - that is all
+ // the Rest layer supports at the moment (16-02)
+ ArrayList <String> currentData = new ArrayList <String> ();
+ if( patchOnly ){
+ // When patching - gotta know what's already in the db
+ Iterator<VertexProperty<Object>> existingPropsIter = (existingVert.properties(entry.getKey()));
+ if( existingPropsIter != null ){
+ while( existingPropsIter.hasNext() ){
+ String existingVal = existingPropsIter.next().value().toString();
+ currentData.add( existingVal );
+ }
+ }
+ }
+ else {
+ // Since this is not a patch-update, we first have to clear out what is currently in the db.
+ existingVert.property(entry.getKey()).remove();
+ }
+
+ if( valIter != null ){
+ while( valIter.hasNext() ){
+ Object thisVal = valIter.next();
+ if( setSoNoDupes ){
+ // For Sets, we need to check that the data isn't already in the db or wasn't passed
+ // in to us twice in the propHash. Otherwise Titan throws an exception (instead of just ignoring it...)
+ if( !currentData.contains(thisVal) ){
+ // We don't have this data yet, so add it to the Set
+ existingVert.property( entry.getKey(), thisVal );
+ currentData.add( thisVal.toString() );
+ }
+ }
+ else {
+ // For List data types, it's ok to have duplicate values in the db (why would we want this?)
+ existingVert.property( entry.getKey(), thisVal );
+ }
+ }
+ }
+ }
+ else {
+ // This is a normal, "Cardinality = SINGLE" kind of property
+ // ResourceVersion is not populated based on passed-in data, it is set along with other internal properties below.
+ //Object cleanVal = convertTypeIfNeeded( entry.getKey(), entry.getValue() );
+ //existingVert.setProperty( entry.getKey(), cleanVal );
+ // ********************************
+ existingVert.property( entry.getKey(), entry.getValue() );
+ }
+ }
+ }
+
+ // DEBUG - trying to deal with the case where simultaneous PUTs
+ // cause our db to wind up with a vertex that does not have these three properties filled in.
+ existingVert.property( "aai-node-type", nodeType );
+ existingVert.property( "aai-created-ts", existingCreateTs );
+ existingVert.property( "source-of-truth", existingSourceOfTruth );
+
+ if( aaiUniqueKeyVal != null ){
+ existingVert.property( "aai-unique-key", aaiUniqueKeyVal );
+ }
+
+ existingVert.property( "aai-last-mod-ts", unixTimeNow );
+ String resVers = "" + unixTimeNow;
+ existingVert.property( "resource-version", resVers );
+ existingVert.property( "last-mod-source-of-truth", fromAppId );
+ msg = msg + ", [aai-last-mod-ts]/[" + unixTimeNow + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, true, "0");
+ return( existingVert );
+ }
+ else{
+ // ----- Not found in the DB, This must be an ADD ------
+ if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = "nodeTypeCategory " + nodeType + " cannot be used to ADD a node. Need to pass a valid nodeType";
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ TitanVertex tiVnew = graph.addVertex( nodeType );
+
+ String msg = "ADD vertex of type = [" + nodeType + "] ";
+ if( depNodeVal != null ){
+ String depNType = depNodeVal.<String>property("aai-node-type").orElse(null);
+ HashMap <String, Object> depNodePropKeysHash = getNodeKeyPropHash(transId, fromAppId, graph, depNodeVal);
+ msg = msg + " onto dependent node: type = " + depNType + ", which has key(s) = [" + depNodePropKeysHash +
+ "]. New Node Prop/values = ";
+ }
+ else {
+ msg = msg + " Note: no dependent node. New Node Prop/values = ";
+ }
+ boolean first = true;
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ if( ! entry.getKey().equals("resource-version") ){
+ if( first ){
+ msg = msg + " [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ first = false;
+ }
+ else {
+ msg = msg + ", [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ }
+
+ boolean nonSingleCardinality = false;
+ boolean setSoNoDupes = false;
+ if( checkPropCardinality(entry.getKey(), "Set") ){
+ nonSingleCardinality = true;
+ setSoNoDupes = true;
+ }
+ else if( checkPropCardinality(entry.getKey(), "List") ){
+ nonSingleCardinality = true;
+ }
+
+ Iterator <Object> valIter = null;
+ if( nonSingleCardinality ){
+ String className = entry.getValue().getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ valIter = ((ArrayList)(entry.getValue())).iterator();
+ }
+ else if( className.equals("List") ){
+ valIter = ((List)(entry.getValue())).iterator();
+ }
+ else if( className.equals("Set") ){
+ valIter = ((Set)(entry.getValue())).iterator();
+ }
+ }
+
+ if( nonSingleCardinality ){
+ // This property has Cardinality of List or Set - which need to be handled carefully
+ ArrayList <String> currentData = new ArrayList <String> ();
+ if( valIter != null ){
+ while( valIter.hasNext() ){
+ Object thisVal = valIter.next();
+ if( setSoNoDupes ){
+ // For Sets, we need to check that they're not passing us duplicate data in propHash.
+ // Otherwise Titan throws an exception (instead of just ignoring it...)
+ if( !currentData.contains(thisVal) ){
+ // We don't have this data yet, so add it to the Set
+ tiVnew.property( entry.getKey(), thisVal );
+ currentData.add( thisVal.toString() );
+ }
+ }
+ else {
+ // For List data types, it's ok to have duplicate values in the db (why would we want this?)
+ tiVnew.property( entry.getKey(), thisVal );
+ }
+ }
+ }
+ }
+ else {
+ // This is a normal, "Cardinality = SINGLE" kind of property
+ // ResourceVersion is not populated based on passed-in data, it is set along with other internal properties below.
+ tiVnew.property( entry.getKey(), entry.getValue() );
+ }
+ }
+ }
+
+ tiVnew.property( "aai-node-type", nodeType );
+ long unixTime = System.currentTimeMillis() / 1000L;
+ tiVnew.property( "aai-created-ts", unixTime );
+ tiVnew.property( "aai-last-mod-ts", unixTime );
+ String resVers = "" + unixTime;
+ tiVnew.property( "resource-version", resVers );
+ tiVnew.property( "source-of-truth", fromAppId );
+ tiVnew.property( "last-mod-source-of-truth", fromAppId );
+ if( aaiUniqueKeyVal != null ){
+ tiVnew.property( "aai-unique-key", aaiUniqueKeyVal );
+ }
+ msg = msg + ", [aai-created-ts]/[" + unixTime + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, true, "0");
+ return( tiVnew );
+ }
+
+ } // end of persistAaiNodeBASE()
+
+
+ /**
+ * Need to do resource ver check.
+ *
+ * @param apiVersion the api version
+ * @param patchOnlyFlag the patch only flag
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean needToDoResourceVerCheck(String apiVersion, Boolean patchOnlyFlag)
+ throws AAIException{
+
+ if( patchOnlyFlag ){
+ // we do not do resource checking for patch requests.
+ return false;
+ }
+
+ String resourceCheckOnFlag = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+
+ int apiVerInt = cleanUpApiVersion(apiVersion);
+
+ if( (resourceCheckOnFlag != null) && resourceCheckOnFlag.equals("true") ){
+ // Only do the check if the resource enable flag is set to "true"
+ if( apiVerInt > 4 ){
+ // We're only doing the resource version checks for v5 and later
+ return true;
+ }
+ }
+
+ return false;
+ }// End needToDoResourceVerCheck()
+
+
+ /**
+ * Clean up api version.
+ *
+ * @param apiVersionString the api version string
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ private static int cleanUpApiVersion( String apiVersionString ) throws AAIException {
+ // Note: we expect an apiVersion to start with the letter "v", followed by an integer.
+
+ int versionInt = 0;
+ String verStr = apiVersionString;
+ if( (apiVersionString == null) || (apiVersionString.length() < 2) ){
+ // Passed in version doesn't look right
+ verStr = org.openecomp.aai.util.AAIApiVersion.get();
+ }
+ versionInt = getVerNumFromVerString( verStr );
+
+ return versionInt;
+ }
+
+ /**
+ * Gets the ver num from ver string.
+ *
+ * @param versionString the version string
+ * @return the ver num from ver string
+ * @throws AAIException the AAI exception
+ */
+ private static int getVerNumFromVerString( String versionString )throws AAIException {
+ int versionInt = 0;
+ if( versionString == null || versionString.length() < 2 ){
+ String detail = " Bad Version (format) passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ int strLen = versionString.length();
+ // We assume that a version looks like "v" followed by an integer
+ if( ! versionString.substring(0,1).equals("v") ){
+ String detail = " Bad Version (format) passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ String intPart = versionString.substring(1,strLen);
+ try {
+ versionInt = Integer.parseInt( intPart );
+ }
+ catch( Exception e ){
+ String detail = " Bad Version passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+ }
+ return versionInt;
+ }
+
+
+ /**
+ * Gets the node key prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeKeyPropNames( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeKeyPropNames");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> keyProps = new ArrayList <String>();
+ if( dbMaps.NodeKeyProps.containsKey(nodeType) ){
+ keyProps = dbMaps.NodeKeyProps.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, so we need to look up the key params
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String keyPropsString = flds[0];
+ String [] propNames = keyPropsString.split("\\|");
+ for( int i = 0; i < propNames.length; i++ ){
+ keyProps.add(propNames[i]);
+ }
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+ // Don't log it when it's ok -- we have way too many of these...
+ //aaiLogger.debug(logline, " end ");
+ return keyProps;
+
+ }// end of getNodeKeyPropNames
+
+ /**
+ * Gets the node key prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the node key prop names
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static Collection <String> getNodeKeyPropNames( String transId, String fromAppId, String nodeType ) throws AAIException{
+ return getNodeKeyPropNames( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Gets the node alt key 1 prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeAltKey1PropNames( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeAltKey1PropNames");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> altKey1Props = new ArrayList <String>();
+ if( dbMaps.NodeAltKey1Props.containsKey(nodeType) ){
+ altKey1Props = dbMaps.NodeAltKey1Props.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, so we need to look up the key params
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ catInfo = catItr.next();
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String altKeyPropsString = flds[1];
+ String [] propNames = altKeyPropsString.split("\\|");
+ for( int i = 0; i < propNames.length; i++ ){
+ altKey1Props.add(propNames[i]);
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return altKey1Props;
+
+ }// end of getNodeAltKey1PropNames
+
+ /**
+ * Gets the node alt key 1 prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the node alt key 1 prop names
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static Collection <String> getNodeAltKey1PropNames( String transId, String fromAppId, String nodeType ) throws AAIException{
+ return getNodeAltKey1PropNames( transId, fromAppId, nodeType, null);
+ }
+
+
+ /**
+ * Gets the unique node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param keyPropsHash the key props hash
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getUniqueNode( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> keyPropsHash, TitanVertex depNodeVal, String apiVersion ) throws AAIException{
+
+ // NOTE - this is really for use by the PersistNode method -- it is looking to see if
+ // a node exists in the database given either Primary or Alternate Key data and dependent
+ // node data (if required for uniqueness).
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getUniqueNode");
+ logline.add("nodeType", nodeType);
+ if( keyPropsHash != null ){
+ logline.add("keyProps", keyPropsHash.toString());
+ }
+
+ // Note - the passed in nodeType could really be a nodeTypeCategory ---
+ Boolean nodeTypeIsCategory = DbEdgeRules.NodeTypeCategory.containsKey(nodeType);
+
+ Boolean useDepNode = false;
+ if( needsADepNode4Uniqueness(transId, fromAppId, nodeType, apiVersion) ){
+ // This kind of node depends on another node for uniqueness
+ if( depNodeVal == null ){
+ // They should have passed in the node that this one depends on
+ String emsg = "null dependentNode object passed to getUniqueNode() but " + nodeType + " requires one.\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else if( ! nodeTypeACanDependOnB(transId, fromAppId, nodeType, depNodeVal.<String>property("aai-node-type").orElse(null), apiVersion) ){
+ // They should have passed in the right type of node as the dependent node
+ String emsg = "dependentNode of type " + depNodeVal.<String>property("aai-node-type").orElse(null) + " passed to getUniqueNode() for nodeType" + nodeType + ".\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ useDepNode = true;
+ }
+ else {
+ depNodeVal = null;
+ }
+
+ // We assume that all NodeTypes have at least one key-property defined. A dependentNode is optional.
+ // Note - instead of key-properties (the primary key properties), a user could pass
+ // alternate-key values if they are defined for the nodeType.
+ ArrayList<String> kName = new ArrayList<String>();
+ ArrayList<Object> kVal = new ArrayList<Object>();
+
+ Collection <String> keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ Boolean haveSomePrimKeyProps = false;
+ Boolean primaryKeyComplete = true;
+ while( keyPropI.hasNext() ){
+ haveSomePrimKeyProps = true;
+
+ String propName = keyPropI.next();
+ if( ! keyPropsHash.containsKey(propName) ){
+ primaryKeyComplete = false;
+ }
+ else {
+ Object valObj = keyPropsHash.get(propName);
+ if( valObj == null ){
+ primaryKeyComplete = false;
+ }
+ else {
+ String value = valObj.toString();
+ if( value == null || value.equals("") ){
+ // They passed the property name, but no value
+ primaryKeyComplete = false;
+ }
+ }
+ }
+ }
+
+ int i = -1;
+ if( haveSomePrimKeyProps && primaryKeyComplete ){
+ keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ String value = (keyPropsHash.get(propName)).toString();
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)value);
+ }
+ }
+ else {
+ // See if they're using the alternate key
+ Collection <String> altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> altKey1PropI = altKey1Props.iterator();
+ Boolean haveSomeAltKey1Props = false;
+ Boolean altKey1Complete = true;
+ while( altKey1PropI.hasNext() ){
+ haveSomeAltKey1Props = true;
+ String propName = altKey1PropI.next();
+ if( ! keyPropsHash.containsKey(propName) ){
+ altKey1Complete = false;
+ }
+ else {
+ Object valObj = keyPropsHash.get(propName);
+ if( valObj == null ){
+ altKey1Complete = false;
+ }
+ else {
+ String value = valObj.toString();
+ if( value == null || value.equals("") ){
+ // They passed the property name, but no value
+ altKey1Complete = false;
+ }
+ }
+ }
+ }
+ if( haveSomeAltKey1Props && altKey1Complete ){
+ altKey1PropI = altKey1Props.iterator();
+ while( altKey1PropI.hasNext() ){
+ String propName = altKey1PropI.next();
+ String value = (keyPropsHash.get(propName)).toString();
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)value);
+ }
+ }
+ }
+
+ int topPropIndex = i;
+ TitanVertex tiV = null;
+ String propsAndValuesForMsg = "";
+ if( !useDepNode ){
+ // There is no node that this type of node depends on, so we can look for it based
+ // solely on the Aai-defined key fields.
+ Iterable <?> verts = null;
+
+ logline.add("topPropIndex", topPropIndex);
+ if( topPropIndex == -1 ){
+ // Problem if no key Properties defined for this nodeType
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Bad or Incomplete Key Property params: (" + keyPropsHash.toString() +
+ ") for nodeType: " + nodeType + " (ver=" + defVer + ")";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6105");
+ throw new AAIException("AAI_6105", detail);
+ }
+ else if( topPropIndex == 0 ){
+ if (nodeTypeIsCategory) // dont know real type
+ verts= graph.query().has(kName.get(0),kVal.get(0)).vertices();
+ else // need this to find dvs switch: dvs.switch-name and port-group.switch-name issue
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") ";
+ }
+ else if( topPropIndex == 1 ){
+ verts = graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ") ";
+ }
+ else if( topPropIndex == 2 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ") ";
+ }
+ else if( topPropIndex == 3 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ", "
+ + kName.get(3) + " = " + kVal.get(3) + ") ";
+ }
+ else {
+ String emsg = " We only support 4 keys per nodeType for now \n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+
+ Iterator <?> vertI = verts.iterator();
+ if( vertI != null && vertI.hasNext()) {
+ // We found a vertex that meets the input criteria.
+ tiV = (TitanVertex) vertI.next();
+
+ if( vertI.hasNext() ){
+ // Since this routine is looking for a unique node for the given input values, if
+ // more than one is found - it's a problem.
+ logline.add("keyProps", propsAndValuesForMsg);
+ aaiLogger.info(logline, false, "AAI_6112");
+ String detail = "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg + "\n";
+ throw new AAIException("AAI_6112", detail);
+ }
+ }
+ else {
+ // No Vertex was found for this key - throw a not-found exception
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ else {
+ // Need to use the dependent vertex to look for this one.
+ // filter this to the actual keys because
+ HashMap<String,Object> onlyKeysHash = new HashMap<String,Object>();
+
+ Collection <String> onlyKeyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+
+ Iterator <String> onlyKeyPropsI = onlyKeyProps.iterator();
+
+ while( onlyKeyPropsI.hasNext() ){
+ String keyName = onlyKeyPropsI.next();
+ onlyKeysHash.put(keyName, keyPropsHash.get(keyName));
+ }
+
+ propsAndValuesForMsg = onlyKeysHash.toString() + " combined with a Dependent [" + depNodeVal.<String>property("aai-node-type").orElse(null) + "] node.";
+ ArrayList<TitanVertex> resultList = DbMeth.getConnectedNodes(transId, fromAppId, graph, nodeType, onlyKeysHash,
+ depNodeVal, apiVersion, false);
+ if( resultList.size() > 1 ){
+ // More than one vertex found when we thought there should only be one.
+ logline.add("keyProps", propsAndValuesForMsg);
+ aaiLogger.info(logline, false, "AAI_6112");
+ String detail = "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg + "\n";
+ throw new AAIException("AAI_6112", detail);
+ }
+ else if( resultList.size() == 1 ){
+ tiV = resultList.get(0);
+ }
+ }
+
+ if( tiV == null ){
+ // No Vertex was found for this key - throw a not-found exception
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ if( !DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The nodeType passed in was a real one, not a nodeTypeCategory, so we will
+ // use it as part of the query to make sure we find the right type of node.
+ // This can be an issue if they're using nodeTypes covered by a nodeTypeCategory but
+ // pass in the wrong nodeType. We don't want them to ask for one thing and get the other.
+ String foundNodeType = tiV.<String>property("aai-node-type").orElse(null);
+ if( foundNodeType != null && !foundNodeType.equals(nodeType) ){
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg + " (did find a " + foundNodeType + " though.)";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ aaiLogger.info(logline, true, "0");
+ return tiV;
+ }
+
+ }// End of getUniqueNode()
+
+ /**
+ * Gets the unique node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param keyPropsHash the key props hash
+ * @param depNodeVal the dep node val
+ * @return the unique node
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex getUniqueNode( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> keyPropsHash, TitanVertex depNodeVal) throws AAIException {
+ return getUniqueNode( transId, fromAppId, graph, nodeType,
+ keyPropsHash, depNodeVal, null );
+ }
+ // End getUniqueNode()
+
+
+ /**
+ * Gets the unique node with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param nodePropsHash the node props hash
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getUniqueNodeWithDepParams( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> nodePropsHash, String apiVersion )
+ throws AAIException{
+ /*
+ * This method uses the nodePropsHash to walk back over dependent nodes until it finds one that
+ * does not depend on any other for uniqueness. It uses the getUniqueNode() method as it finds
+ * dependent nodes. NOTE -- it is passed a hash of all the nodeProperties -- for itself and
+ * for any dependent nodes that it will need to find. There are some types of nodes that can
+ * depend on more than one node, we assume that there wouldn't be a case where BOTH types of
+ * dependent nodes are in the trail that we need to traverse. Ie. an ipaddress can depend on
+ * either a vserver or pserver. NOTE this case can now happen -- nodePropsHash
+ * should now be sent as a LinkedHashMap in this case so we can search in order.
+ */
+
+ // NOTE ALSO -- We're currently supporting 6 layers of dependency. We never thought there would be this
+ // many layers before hitting a node-type that would be uniquely identifiable on it's own. So the
+ // code is a little ugly with all these nested if-then-else's. Since we're supporting so many
+ // layers, it should be re-written so we can support "n" layers instead of having to go in hear
+ // and adding code... But as of 15-07, we really don't NEED more than 5.
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getUniqueNodeWithDepParams");
+ logline.add("nodeType", nodeType);
+ if( nodePropsHash != null ){
+ logline.add("nodeProps", nodePropsHash.toString());
+ }
+
+ // NOTE: The passed in nodeType could really be a nodeTypeCategory --
+ // The calls to figureDepNodeTypeForRequest() below will deal with it for the dep nodes, the
+ // call to getUniqueNode() takes care of it for the node itself.
+
+ TitanVertex nullVert = null;
+ String depNodeType = figureDepNodeTypeForRequest( transId, fromAppId, nodeType, nodePropsHash, apiVersion );
+ if( depNodeType.equals("")){
+ // This kind of node does not depend on another node for uniqueness, so
+ // we can just use the "getUniqueNode()" method to get it.
+ aaiLogger.info(logline, true, "0");
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, nullVert, apiVersion) );
+ }
+ else {
+ // Will need to find the second-layer dependent node
+ String secondLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, depNodeType, nodePropsHash, apiVersion );
+ if( secondLayerDepNodeType.equals("")){
+ // This second-layer kind of node does not depend on another node for uniqueness.
+ // So once we find the second-layer node, we can use it to get the top-layer guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the third-layer dependent node
+ /// String thirdLayerDepNodeType = dbMaps.NodeDependencies.get(secondLayerDepNodeType);
+ String thirdLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion );
+
+ if( thirdLayerDepNodeType.equals("")){
+ // This third-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the third-layer dependent node
+ String forthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion );
+ if( forthLayerDepNodeType == null || forthLayerDepNodeType.equals("")){
+ // This forth-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the forth-layer dependent node
+ String fifthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion );
+ if( fifthLayerDepNodeType == null || fifthLayerDepNodeType.equals("")){
+ // This fifth-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the forth, third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex fifthLayerDepVert = getUniqueNode(transId, fromAppId, graph, forthLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, fifthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the fifth-layer dependent node
+ String sixthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, fifthLayerDepNodeType, nodePropsHash, apiVersion );
+ if( sixthLayerDepNodeType == null || sixthLayerDepNodeType.equals("")){
+ // This six-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the fifth, forth, third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, fifthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex sixthLayerDepVert = getUniqueNode(transId, fromAppId, graph, fifthLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex fifthLayerDepVert = getUniqueNode(transId, fromAppId, graph, forthLayerDepNodeType, thisNodeTypeParamHash, sixthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, fifthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // We don't currently support more layers. We can later if we need to.
+ // Hopefully, we'll never need to go this deep -- there should be unique keys in there somewhere!
+ String detail = "CODE-LIMITATION - Can't resolve dependant node layers for nodeType = " + nodeType;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", detail);
+ }
+ }
+ }
+ }
+ }
+ }
+ } // End getUniqueNodeWithDepParams()
+
+ /**
+ * Gets the unique node with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param nodePropsHash the node props hash
+ * @return the unique node with dep params
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex getUniqueNodeWithDepParams( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> nodePropsHash ) throws AAIException {
+ return getUniqueNodeWithDepParams(transId, fromAppId, graph, nodeType, nodePropsHash, null);
+ }
+
+
+ /**
+ * Gets the this node type params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param targetNodeType the target node type
+ * @param passedHash the passed hash
+ * @param apiVersion the api version
+ * @return the this node type params
+ * @throws AAIException the AAI exception
+ */
+ private static HashMap <String, Object> getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType,
+ HashMap<String,Object> passedHash, String apiVersion )throws AAIException{
+ /*
+ * For the passed-in hash, each key is assumed to look like, "nodeType.paramName". We want to
+ * pick out the entries that match the targetNodeType and return those with the values they go with. The
+ * returned keys will have the "nodeType." stripped off.
+ *
+ * NOTE - the nodeType passed to this method could actually be a nodeTypeCategory. Just keepin it ugly.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getThisNodeTypeParams");
+ logline.add("targetNodeType", targetNodeType);
+ if( passedHash == null ){
+ String detail = "Bad param: null passedHash ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ logline.add("passedHash", passedHash.toString());
+
+ String targetNodeTypeCat = "";
+ if( DbEdgeRules.NodeTypeCatMap.containsKey(targetNodeType) ){
+ targetNodeTypeCat = DbEdgeRules.NodeTypeCatMap.get(targetNodeType);
+ }
+
+ HashMap <String,Object> returnHash = new HashMap <String,Object> ();
+ Iterator <Map.Entry<String,Object>>it = passedHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <String,Object>pairs = (Map.Entry<String,Object>)it.next();
+ String k = (pairs.getKey()).toString();
+ int periodLoc = k.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String nty = k.substring(0,periodLoc);
+ String paramName = k.substring(periodLoc + 1);
+ if( nty.equals(targetNodeType) || (!targetNodeTypeCat.equals("") && nty.equals(targetNodeTypeCat)) ){
+ String newK = paramName;
+ returnHash.put( newK,pairs.getValue() );
+ }
+ }
+ }
+
+ //aaiLogger.debug(logline, " - end ");
+ return returnHash;
+
+ }// End of getThisNodeTypeParams()
+
+ /**
+ * Gets the this node type params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param targetNodeType the target node type
+ * @param passedHash the passed hash
+ * @return the this node type params
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static HashMap <String, Object> getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType,
+ HashMap<String,Object> passedHash )throws AAIException{
+ return getThisNodeTypeParams( transId, fromAppId, targetNodeType,
+ passedHash, null);
+
+ }
+
+ /**
+ * Gets the dep node types.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the dep node types
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <String> getDepNodeTypes(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ /*
+ * This returns any nodeTypes that this nodeType can be dependent on. A particular instance of a node will only
+ * depend on one other node - we don't currently support dependence on multiple nodes.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getDepNodeTypes");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ ArrayList <String> depNodeTypeL = new ArrayList <String> ();
+ if( !DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // This is a good-ole nodeType
+ Collection <String> depNTColl = dbMaps.NodeDependencies.get(nodeType);
+ Iterator <String> ntItr = depNTColl.iterator();
+ while( ntItr.hasNext() ){
+ depNodeTypeL.add(ntItr.next());
+ }
+ }
+ else {
+ // The passed-in nodeType must really be a nodeTypeCategory
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6121");
+ String detail = "Error getting DbEdgeRules.NodeTypeCategory info for nodeTypeCat = " + nodeType;
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String nodeTypesString = flds[0];
+ String hasDepNodes = flds[3];
+ if( hasDepNodes.equals("true") ){
+ String [] ntNames = nodeTypesString.split("\\|");
+ for( int i = 0; i < ntNames.length; i++ ){
+ Collection <String> depNTColl = dbMaps.NodeDependencies.get(nodeType);
+ Iterator <String> ntItr = depNTColl.iterator();
+ while( ntItr.hasNext() ){
+ String depNode = ntItr.next();
+ if( !depNodeTypeL.contains(depNode) ){
+ depNodeTypeL.add(depNode);
+ }
+ }
+ }
+ }
+ }
+
+
+ //aaiLogger.debug(logline, " end ");
+ return depNodeTypeL;
+
+ }// End getDepNodeTypes()
+
+ /**
+ * Gets the dep node types.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the dep node types
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList <String> getDepNodeTypes(String transId, String fromAppId, String nodeType)throws AAIException{
+ return getDepNodeTypes( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Gets the default delete scope.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the default delete scope
+ * @throws AAIException the AAI exception
+ */
+ private static String getDefaultDeleteScope(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getDefaultDeleteScope");
+ logline.add("nodeType", nodeType);
+
+ // At some point we may have different delete rules for different services, so this is
+ // a list for now even thought there's only one scope per nodeType.
+ Collection <String> scopeList = DbEdgeRules.DefaultDeleteScope.get(nodeType);
+ if( scopeList.isEmpty() ){
+ String detail = "No default deleteScope found for nodeType = [" + nodeType + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ aaiLogger.debug(logline, " end ");
+ Iterator <String> ito = scopeList.iterator();
+ return ito.next();
+ }
+
+ }// End getDefaultDeleteScope()
+
+ /**
+ * Gets the default delete scope.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the default delete scope
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static String getDefaultDeleteScope(String transId, String fromAppId, String nodeType)throws AAIException{
+ return getDefaultDeleteScope( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Needs A dep node 4 uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean needsADepNode4Uniqueness(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ // Note: the passed in nodeType could really be a nodeTypeCategory. That is handled by getDepNodeTypes()
+
+ ArrayList <String> depList = getDepNodeTypes(transId, fromAppId, nodeType, apiVersion);
+ if( depList.isEmpty() ){
+ return false;
+ }
+ else {
+ return true;
+ }
+
+ }// End needsADepNode4Uniqueness()
+
+ /**
+ * Needs A dep node 4 uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static Boolean needsADepNode4Uniqueness(String transId, String fromAppId, String nodeType)throws AAIException{
+ return needsADepNode4Uniqueness( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Node type A can depend on B.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @param apiVersion the api version
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean nodeTypeACanDependOnB(String transId, String fromAppId, String nodeTypeA, String nodeTypeB, String apiVersion)
+ throws AAIException{
+ // Note: the passed in nodeType could really be a nodeTypeCategory. That is handled by getDepNodeTypes()
+
+ ArrayList <String> depList = getDepNodeTypes(transId, fromAppId, nodeTypeA, apiVersion);
+ if( depList.isEmpty() ){
+ return false;
+ }
+ else if( depList.contains(nodeTypeB) ){
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ }// End nodeTypeACanDependOnB()
+
+ /**
+ * Node type A can depend on B.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static Boolean nodeTypeACanDependOnB(String transId, String fromAppId, String nodeTypeA, String nodeTypeB)
+ throws AAIException{
+ return nodeTypeACanDependOnB( transId, fromAppId, nodeTypeA, nodeTypeB, null);
+ }
+
+ /**
+ * Figure dep node type for request.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param requestParamHash the request param hash
+ * @param apiVersion the api version
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String figureDepNodeTypeForRequest(String transId, String fromAppId, String nodeType,
+ HashMap<String,Object> requestParamHash, String apiVersion )throws AAIException{
+ /*
+ * This is ugly. But if the passed-in nodeType is dependent on another nodeType for
+ * uniqueness, we need to return what that dependent node-type is. The ugly comes in
+ * because a node can be dependent on more than one type of node. So, to tell which one
+ * is going to apply, we root through the passed request parameters to see which of
+ * the possible dependent node types is being used.
+ * Note -- if there comes a day when there are so many dependencies that the request could
+ * have more than one that match -- Then we need to think up something new. But for now,
+ * we have to assume that if there are more than one legal dep-node-types, only one will
+ * be represented in the requestHash data. >>> NOTE >>> That day has come. For
+ * the upstreamers will send in a LinkedHashMap instead of just an unordered
+ * HashMap so we can look in order for the dependent node.
+ *
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "figureDepNodeTypeForRequest");
+ logline.add("nodeType", nodeType);
+ if( requestParamHash == null ){
+ String detail = "Bad param: null requestParamHash ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ logline.add("requestParamHash", requestParamHash.toString());
+
+ ArrayList <String> depNodeTypes = getDepNodeTypes(transId, fromAppId, nodeType, apiVersion);
+ if( depNodeTypes.isEmpty() ){
+ // This kind of node is not dependent on any other
+ //aaiLogger.debug(logline, " (not dependent) - end ");
+ return "";
+ }
+ else if( depNodeTypes.size() == 1 ){
+ // This kind of node can only depend on one other nodeType - so return that.
+ //aaiLogger.debug(logline, " (depends on " + depNodeTypes.get(0) + " - end ");
+ return depNodeTypes.get(0);
+ }
+ else {
+ // We need to look to find the first of the dep-node types that is represented in the passed-in
+ // request data. That will be the one we need to use.
+
+ // first find out what node-types are represented in the requestHash
+
+ Iterator <Map.Entry<String,Object>>it = requestParamHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <String,Object>pairs = (Map.Entry<String,Object>)it.next();
+ String k = (pairs.getKey()).toString();
+ int periodLoc = k.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String nty = k.substring(0,periodLoc);
+ if( depNodeTypes.contains(nty) ){
+ // This is the first possible dep. node type we've found for the passed in data set
+ return nty;
+ }
+ }
+ }
+
+ }
+
+ // It's not an error if none is found - the caller needs to deal with cases where there
+ // should be a dep. node identified but isn't.
+ //aaiLogger.debug(logline, " no dep NT found - end ");
+ return "";
+
+ }// End of figureDepNodeTypeForRequest()
+
+ /**
+ * Figure dep node type for request.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param requestParamHash the request param hash
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static String figureDepNodeTypeForRequest(String transId, String fromAppId, String nodeType,
+ HashMap<String,Object> requestParamHash )throws AAIException{
+ return figureDepNodeTypeForRequest( transId, fromAppId, nodeType, requestParamHash, null);
+ }
+
+ /**
+ * Detach connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param autoDeleteOrphans the auto delete orphans
+ * @param apiVersion the api version
+ * @return deletedNodeCount
+ * @throws AAIException the AAI exception
+ */
+ public static int detachConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, boolean autoDeleteOrphans, String apiVersion ) throws AAIException{
+
+ /* Find nodes that are attached to this node which meet the nodeType/filterParams criteria.
+ * Remove the edges that go to those nodes.
+ * If that turns any of the nodes into an orphan, then delete it if the autoDeleteOrphans flag is set.
+ * Return a count of how many nodes were actually deleted (not just detached).
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "detachConnectedNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+
+ int deletedCount = 0;
+
+ if( startNodeVal == null ){
+ // They should have passed in the node that this query starts from
+ String emsg = "null startNode object passed to detachConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+
+ // We want to loop through the connected Nodes that we found.
+ // For each connected Node, we'll get the all edges that start from that node and look for the one
+ // that connects back to our startNode.
+ // Only delete the edge that connects back to our startNode.
+ // then autoDeleteOrphans flag is set, then delete the connectedNode if it's now orphaned.
+ //
+
+ String startNodeVId = startNodeVal.id().toString();
+ ArrayList<TitanVertex> conNodeList = getConnectedNodes( transId, fromAppId, graph, nodeType, propFilterHash, startNodeVal, apiVersion, false );
+ Iterator<TitanVertex> conVIter = conNodeList.iterator();
+ while( conVIter.hasNext() ){
+ TitanVertex connectedVert = conVIter.next();
+ boolean isFirstOne = true;
+ Iterator<Edge> eI = connectedVert.edges(Direction.BOTH);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(connectedVert);
+ String otherSideLookingBackVId = otherVtx.id().toString();
+ if( startNodeVId.equals(otherSideLookingBackVId) ){
+ // This is an edge from the connected node back to our starting node
+ if( isFirstOne && !eI.hasNext() && autoDeleteOrphans ){
+ // This was the one and only edge for this connectedNode, so
+ // delete the node and edge since flag was set
+ String resVers = connectedVert.<String>property("resource-version").orElse(null);
+ removeAaiNode( transId, fromAppId, graph, connectedVert, "USE_DEFAULT", apiVersion, resVers);
+ deletedCount = deletedCount + 1;
+ }
+ else {
+ removeAaiEdge( transId, fromAppId, graph, ed );
+ }
+ }
+ isFirstOne = false;
+ }
+ }
+ aaiLogger.info(logline, true, "0");
+ return deletedCount;
+
+ } // end of detachConnectedNodes()
+
+
+
+ /**
+ * Detach connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param autoDeleteOrphans the auto delete orphans
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static int detachConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, boolean autoDeleteOrphans ) throws AAIException{
+ return detachConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, autoDeleteOrphans, null);
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @param apiVersion the api version
+ * @return ArrayList<TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose, String apiVersion ) throws AAIException{
+ boolean skipGroomingFlag = true;
+ // we will only do real-time grooming if a system variable is set, telling us not to skip it.
+ String skipGroomingStr = AAIConstants.AAI_SKIPREALTIME_GROOMING;
+ if( skipGroomingStr.equals("false") ){
+ skipGroomingFlag = false;
+ }
+ return( getNodes(transId, fromAppId, graph, nodeType, propFilterHash, noFilterOnPurpose, apiVersion, skipGroomingFlag) );
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @param apiVersion the api version
+ * @param skipGroomCheck the skip groom check
+ * @return ArrayList<TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose, String apiVersion, boolean skipGroomCheck )
+ throws AAIException{
+ // Note - the skipGroomCheck flag is set to true when the DataGrooming tool is using this method to collect
+ // node data. When the grooming tool is collecting data, we don't want any nodes skipped, because we
+ // want details about what nodes/edges are bad - more detail than the check in this method does
+ // as it checks if a node is ok to return to a caller.
+
+ /* Use the nodeType + filterParams to find nodes.
+ */
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ ArrayList<TitanVertex> returnVertList = new ArrayList<TitanVertex>();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+ if( nodeType == null || nodeType.equals("") ){
+ // They should have passed in a nodeType
+ String emsg = "Required field: nodeType not passed to getNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ if( !noFilterOnPurpose && (propFilterHash == null || propFilterHash.isEmpty()) ){
+ // They should have passed at least one property to filter on
+ String emsg = "Required field: propFilterHash not passed to getNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList<String> kName = new ArrayList<String>();
+ ArrayList<Object> kVal = new ArrayList<Object>();
+ int i = -1;
+ Collection <String> indexedProps = dbMaps.NodeMapIndexedProps.get(nodeType);
+ // First loop through to pick up the indexed-properties if there are any being used
+
+ if( propFilterHash != null ){
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) it.next();
+ String propName = (propEntry.getKey()).toString();
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ if( indexedProps.contains(propName) ){
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)propEntry.getValue());
+ }
+ }
+ }
+
+ // Now go through again and pick up the non-indexed properties
+ it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <?,?> propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ if( ! indexedProps.contains(propName) ){
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)propEntry.getValue());
+ }
+ }
+ }
+ }
+
+ Iterable <?> verts = null;
+ String propsAndValuesForMsg = "";
+ int topPropIndex = i;
+ if( topPropIndex == -1 ){
+ // No Filtering -- just go get them all
+ verts= graph.query().has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " ( no filter props ) ";
+ }
+ else if( topPropIndex == 0 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") ";
+ }
+ else if( topPropIndex == 1 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ") ";
+ }
+ else if( topPropIndex == 2 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ") ";
+ }
+ else if( topPropIndex == 3 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ", "
+ + kName.get(3) + " = " + kVal.get(3) + ") ";
+ }
+ else {
+ String emsg = " -- Sorry -- we only support 4 filter properties in getNodes() for now... \n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ if( verts != null ){
+ // We did find some matching vertices
+ Iterator <?> it = verts.iterator();
+ while( it.hasNext() ){
+ TitanVertex v = (TitanVertex)it.next();
+
+ if( skipGroomCheck ){
+ // Good or bad, just return everything we find
+ returnVertList.add( v );
+ }
+ else {
+ // Weed out any bad vertices we find
+ if( thisVertexNotReachable(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - Unreachable Node DETECTED > skipping it. ";
+ logline.add("msg", msg);
+ }
+ else if( thisVertexHasBadEdges(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - BAD EDGE DETECTED > skipping vtxId = [" + v.id() + "] ";
+ logline.add("msg", msg);
+ }
+ else if( thisVertexIsAPhantom(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - BAD NODE DETECTED > skipping vtxId = [" + v.id() + "] ";
+ logline.add("msg", msg);
+ }
+ else {
+ returnVertList.add( v );
+ }
+ }
+ }
+ }
+ logline.add("passedValues", propsAndValuesForMsg);
+ aaiLogger.info(logline, true, "0");
+ return returnVertList;
+
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @return the nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose ) throws AAIException{
+ return getNodes(transId, fromAppId, graph, nodeType,
+ propFilterHash, noFilterOnPurpose, null );
+ }
+ // End of getNodes()
+
+
+ /**
+ * Gets the connected children.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVtx the start vtx
+ * @param limitToThisNodeType the limit to this node type
+ * @return ArrayList <TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getConnectedChildren( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVtx, String limitToThisNodeType ) throws AAIException{
+
+ // Just get child nodes (ie. other end of an OUT edge that is tagged as a parent/Child edge)
+
+ ArrayList <TitanVertex> childList = new ArrayList <TitanVertex> ();
+ Boolean doNodeTypeCheck = false;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getConnectedChildren");
+ if( limitToThisNodeType != null && ! limitToThisNodeType.equals("") ){
+ doNodeTypeCheck = true;
+ }
+ Iterable <?> verts = startVtx.query().direction(Direction.OUT).has("isParent",true).vertices();
+ Iterator <?> vertI = verts.iterator();
+ TitanVertex tmpVtx = null;
+ while( vertI != null && vertI.hasNext() ){
+ tmpVtx = (TitanVertex) vertI.next();
+ if( ! doNodeTypeCheck ){
+ childList.add(tmpVtx);
+ }
+ else {
+ String tmpNT = tmpVtx.<String>property("aai-node-type").orElse(null);
+ if( tmpNT != null && tmpNT.equals(limitToThisNodeType) ){
+ childList.add(tmpVtx);
+ }
+ }
+ }
+
+ return childList;
+
+ }// End of getConnectedChildren()
+
+
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param apiVersion the api version
+ * @param excludeRecurComingIn the exclude recur coming in
+ * @return ArrayList <TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, String apiVersion, Boolean excludeRecurComingIn ) throws AAIException{
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ /* Get (almost) all the nodes that are connected to this vertex.
+ * Narrow down what is returned using optional filter parameters nodeType and propFilterHash
+ * NOTE - the default behavior has changed slightly. For start-Nodes that
+ * can be recursivly connected, this method will only bring back the same kind of
+ * connected node by following an OUT edge. Ie. if the start node is an "model-element",
+ * then this method will only follow OUT edges to get to other "model-element" type nodes.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getConnectedNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+
+ String startNodeNT = "";
+ if( startNodeVal == null ){
+ // They should have passed in the node that this query starts from
+ String emsg = "null startNode object passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else {
+ startNodeNT = startNodeVal.<String>property("aai-node-type").orElse(null);
+ }
+
+ boolean nodeTypeFilter = false;
+ if( nodeType != null && !nodeType.equals("") ){
+ // They want to filter using nodeType
+ if( ! dbMaps.NodeProps.containsKey(nodeType) ){
+ String emsg = " Unrecognized nodeType [" + nodeType + "] passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6115");
+ throw new AAIException("AAI_6115", emsg);
+ }
+ nodeTypeFilter = true;
+ }
+
+ ArrayList <String> excludeVidList = new <String> ArrayList ();
+ if( DbEdgeRules.CanBeRecursiveNT.containsKey(startNodeNT) && excludeRecurComingIn ){
+ // If we're starting on a nodeType that supports recursion, then find any connected
+ // nodes that are coming from IN edges so we can exclude them later.
+
+ Iterable <?> vertsR = startNodeVal.query().direction(Direction.IN).vertices();
+ Iterator <?> vertIR = vertsR.iterator();
+ while( vertIR != null && vertIR.hasNext() ){
+ TitanVertex tmpVertIN = (TitanVertex) vertIR.next();
+ String tmpNT = tmpVertIN.<String>property("aai-node-type").orElse(null);
+ if( tmpNT != null && tmpNT.equals(startNodeNT) ){
+ // We're on a nodetype that supports recursion (like model-element) and we've
+ // found an connected Node of this same type on an IN edge - put this
+ // on our excludeList.
+ excludeVidList.add( tmpVertIN.id().toString() );
+ }
+ }
+ }
+
+ boolean propertyFilter = false;
+ if( propFilterHash != null && !propFilterHash.isEmpty() ){
+ // They want to filter using some properties
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ if( ! dbMaps.NodeProps.containsValue(propName) ){
+ String emsg = " Unrecognized property name [" + propName + "] passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6116");
+ throw new AAIException("AAI_6116", emsg);
+ }
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ propertyFilter = true;
+ }
+ }
+ }
+ // If filter-properties were passed in, then look for nodes that have those values.
+ ArrayList<TitanVertex> returnVertList = new ArrayList<TitanVertex>();
+ Iterable<TitanVertex> qResult = null;
+ Iterator<TitanVertex> resultI = null;
+ try {
+ qResult = startNodeVal.query().vertices();
+ resultI = qResult.iterator();
+ }
+ catch( NullPointerException npe ){
+ String emsg = "Titan null pointer exception trying to get nodes connected to vertexId = " +
+ startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "].";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ while( resultI != null && resultI.hasNext() ){
+ boolean addThisOne = true;
+ TitanVertex tmpV = (TitanVertex)resultI.next();
+ if( tmpV == null ){
+ String emsg = "Titan gave a null vertex when looking for nodes connected to vertexId = " +
+ startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "].";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+
+ else {
+ String tmpVid = tmpV.id().toString();
+ if( nodeTypeFilter ){
+ Object nto = tmpV.<Object>property("aai-node-type").orElse(null);
+ if( nto == null || !nto.toString().equals(nodeType) ){
+ String emsg = "Found a connected vertex (vertexId = " +
+ tmpVid + "), but it had no aai-node-type property. ";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+ }
+
+ if( excludeVidList.contains(tmpVid) ){
+ String emsg = "Found a connected vertex (vertexId = " +
+ tmpVid + "), but will exclude it since it is on an IN edge and this nodeType " +
+ startNodeNT + " can be recursively attached.";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+
+ if( propertyFilter ){
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <?,?>propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ if( checkPropCardinality(propName, "Set") || checkPropCardinality(propName, "List") ){
+ // Don't allow search on properties that do not have SINGLE cardinality
+ continue;
+ }
+ Object propVal = propEntry.getValue();
+ Object foundVal = tmpV.<Object>property(propName).orElse(null);
+ if( foundVal != null && propVal != null && !foundVal.toString().equals(propVal.toString()) ){
+ addThisOne = false;
+ break;
+ }
+ else if( (foundVal == null && propVal != null) || (foundVal != null && propVal == null) ){
+ addThisOne = false;
+ break;
+ }
+ }
+ }
+ }
+ if( addThisOne ){
+ // This node passed the tests -- put it on the return List
+ returnVertList.add( (TitanVertex)tmpV );
+ }
+ }
+ //aaiLogger.debug(logline, " end ");
+ return returnVertList;
+
+ }// End of getConnectedNodes()
+
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param apiVersion the api version
+ * @return the connected nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, String apiVersion ) throws AAIException {
+ return getConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, apiVersion, true );
+ }
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @return the connected nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal ) throws AAIException {
+ return getConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, null, true );
+
+ }
+
+ /**
+ * Ip address format OK.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param addrVal the addr val
+ * @param addrVer the addr ver
+ * @param apiVersion the api version
+ * @return Boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean ipAddressFormatOK(String transId, String fromAppId, String addrVal, String addrVer, String apiVersion) throws AAIException{
+
+ /* NOTE -- the google methods we use do not allow leading zeros in ipV4 addresses.
+ * So it will reject, "22.33.44.001"
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "ipAddressFormatOK");
+ logline.add("addrVal", addrVal);
+ logline.add("addrVer", addrVer);
+
+ if( addrVal == null ){
+ String emsg = " Bad data (addrVal = null) passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else if( addrVer == null ){
+ String emsg = " Bad data (addrType = null) passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+
+ Boolean retVal = false;
+ Boolean lookingForV4 = false;
+ Boolean lookingForV6 = false;
+ InetAddress inetAddr = null;
+
+ if( addrVer.equalsIgnoreCase("v4") || addrVer.equals("ipv4") || addrVer.equals("4")){
+ lookingForV4 = true;
+ }
+ else if( addrVer.equalsIgnoreCase("v6") || addrVer.equals("ipv6") || addrVer.equals("6")){
+ lookingForV6 = true;
+ }
+ else {
+ String emsg = " Bad data for addressVersion [" + addrVer + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+
+ try {
+ inetAddr = InetAddresses.forString(addrVal);
+ if( inetAddr instanceof Inet4Address ){
+ if( lookingForV4 ){
+ retVal = true;
+ }
+ else {
+ String emsg = " Bad data. Address is a V4, but addressType said it should be V6. ["
+ + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ else if( inetAddr instanceof Inet6Address ){
+ if( lookingForV6 ){
+ retVal = true;
+ }
+ else {
+ String emsg = " Bad data. Address is a V6, but addressType said it should be V4. ["
+ + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ }
+ catch (IllegalArgumentException e) {
+ String emsg = " Badly formed ip-address: [" + addrVal + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ aaiLogger.info(logline, true, "0");
+ return retVal;
+
+ }//end of ipAddressFormatOk()
+
+ /**
+ * Ip address format OK.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param addrVal the addr val
+ * @param addrVer the addr ver
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean ipAddressFormatOK(String transId, String fromAppId, String addrVal, String addrVer) throws AAIException{
+ return ipAddressFormatOK( transId, fromAppId, addrVal, addrVer, null);
+ }
+
+ /**
+ * Save aai edge to db.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param outV the out V
+ * @param inV the in V
+ * @param propHash the prop hash
+ * @param apiVersion the api version
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ private static TitanEdge saveAaiEdgeToDb(String transId, String fromAppId, TitanTransaction graph, String edgeLabel,
+ TitanVertex outV, TitanVertex inV, HashMap <String,Object> propHash, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "saveAaiEdgeToDb");
+
+
+ // If this edge doesn't exist yet, then create it.
+
+ // NOTE - the Titan javaDoc says that there might not always be an id for a node.
+ // This is the internal-titan-unique-id, not any of our data.
+ // Not sure how to know when it might be there and when it might not?!
+ // So far, it has worked for all my testing, but this might warrant some
+ // further investigation.
+
+ TitanEdge existingEdge = null;
+ String inVId = inV.id().toString();
+ Iterator <Edge> eI = outV.edges(Direction.BOTH, edgeLabel);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(outV);
+ if( (otherVtx.id().toString()).equals(inVId) ){
+ // NOTE -?- Not sure -- at some point we might want to check the edgeLabels also since we might
+ // want to allow two different-type edges between the same two vertexes? (or maybe not.)
+ existingEdge = ed;
+ break;
+ }
+ }
+
+ if( existingEdge != null ){
+ // This is just an UPDATE
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ String msg = "update edge property/val = [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ logline.add("msg", msg);
+ existingEdge.property( entry.getKey(), entry.getValue() );
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return( existingEdge );
+ }
+ else {
+ // This is an ADD
+
+ // Uniqueness double-check. This is just to catch the possibility that at the transaction layer,
+ // if data came in for two identical nodes that point to the same dependant node (for uniqueness),
+ // we would only be able to catch the problem at the time the edge to the second node is added.
+ // For example - if they had a VM and then got a request to add two ipAddress nodes, but some
+ // bad data was passed and those two ipAddress nodes were identical -- we'd want to catch it.
+ String outV_NType = outV.<String>property("aai-node-type").orElse(null);
+ String inV_NType = inV.<String>property("aai-node-type").orElse(null);
+ if( needsADepNode4Uniqueness(transId, fromAppId, outV_NType, apiVersion)
+ && nodeTypeACanDependOnB(transId, fromAppId, outV_NType, inV_NType, apiVersion) ){
+ // The out-Vertex has a uniqueness dependency on the in-vertex
+ // Make sure we haven't already added an node/edge like this in this transaction
+ HashMap <String, Object> nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, outV);
+ ArrayList<TitanVertex> resultList = new ArrayList<TitanVertex>();
+ resultList = DbMeth.getConnectedNodes("transId", "fromAppId", graph, outV_NType, nodeKeyPropsHash, inV, apiVersion, false);
+ if( resultList.size() > 0 ){
+ aaiLogger.info(logline, false, "AAI_6117");
+ String propInfo = "";
+ if( nodeKeyPropsHash != null ){
+ propInfo = nodeKeyPropsHash.toString();
+ }
+ String detail = "Failed to add edge. This node (" + inV_NType + ") already has an edge to a " + outV_NType +
+ " node with kepProps [" + propInfo + "]\n";
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+ else if( needsADepNode4Uniqueness(transId, fromAppId, inV_NType, apiVersion)
+ && nodeTypeACanDependOnB(transId, fromAppId, inV_NType, outV_NType, apiVersion) ){
+ // The in-Vertex has a uniqueness dependency on the out-vertex
+ // Make sure we haven't already added an node/edge like this in this transaction
+ HashMap <String, Object> nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, inV);
+ ArrayList<TitanVertex> resultList = new ArrayList<TitanVertex>();
+ resultList = DbMeth.getConnectedNodes("transId", "fromAppId", graph, inV_NType, nodeKeyPropsHash, outV, apiVersion, false);
+ if( resultList.size() > 0 ){
+ aaiLogger.info(logline, false, "AAI_6117");
+ String propInfo = "";
+ if( nodeKeyPropsHash != null ){
+ propInfo = nodeKeyPropsHash.toString();
+ }
+ String detail = "Failed to add edge. This node (" + outV_NType + ") already has an edge to a " + inV_NType +
+ " node with kepProps [" + propInfo + "]\n";
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+
+
+ // We're good to go to add this edge
+
+ TitanEdge tEdge = outV.addEdge( edgeLabel, inV );
+ // Add the properties to the new Edge
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ tEdge.property( entry.getKey(), entry.getValue() );
+ }
+
+ // For (resource-id updates) we need to "touch" the vertices on each side of the edge so
+ // anybody working on one of those vertices will know that something (ADDing this edge) has happened.
+ touchVertex( transId, fromAppId, inV );
+ touchVertex( transId, fromAppId, outV );
+
+ aaiLogger.debug(logline, " end ");
+ return tEdge;
+ }
+
+ }// End saveAaiEdgeToDb()
+
+
+
+ /**
+ * Derive edge rule key for this edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param tEdge the t edge
+ * @return String - key to look up edgeRule (fromNodeType|toNodeType)
+ * @throws AAIException the AAI exception
+ */
+ public static String deriveEdgeRuleKeyForThisEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanEdge tEdge ) throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deriveEdgeRulesKeyForThisEdge");
+
+ TitanVertex fromVtx = tEdge.outVertex();
+ TitanVertex toVtx = tEdge.inVertex();
+ String startNodeType = fromVtx.<String>property("aai-node-type").orElse(null);
+ String targetNodeType = toVtx.<String>property("aai-node-type").orElse(null);
+ String key = startNodeType + "|" + targetNodeType;
+ if( DbEdgeRules.EdgeRules.containsKey(key) ){
+ // We can use the node info in the order they were given
+ return( key );
+ }
+ else {
+ key = targetNodeType + "|" + startNodeType;
+ if( DbEdgeRules.EdgeRules.containsKey(key) ){
+ return( key );
+ }
+ else {
+ // Couldn't find a rule for this edge
+ String detail = "No EdgeRule found for passed nodeTypes: " + startNodeType + ", "
+ + targetNodeType ;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ }
+ }// end of deriveEdgeRuleKeyForThisEdge()
+
+
+
+ /**
+ * Save aai edge to db.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param outV the out V
+ * @param inV the in V
+ * @param propHash the prop hash
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static TitanEdge saveAaiEdgeToDb(String transId, String fromAppId, TitanTransaction graph, String edgeLabel,
+ TitanVertex outV, TitanVertex inV, HashMap <String,Object> propHash) throws AAIException{
+ return saveAaiEdgeToDb( transId, fromAppId, graph, edgeLabel,
+ outV, inV, propHash, null);
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param apiVersion the api version
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert, String apiVersion ) throws AAIException{
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion, "");
+ return returnEdge;
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param apiVersion the api version
+ * @param edgeType the edge type
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert, String apiVersion, String edgeType ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdge");
+
+ TitanVertex fromVtx = null;
+ TitanVertex toVtx = null;
+ String startNodeType = startVert.<String>property("aai-node-type").orElse(null);
+ String targetNodeType = targetVert.<String>property("aai-node-type").orElse(null);
+ String fwdRuleKey = startNodeType + "|" + targetNodeType;
+ int fwdRuleCount = 0;
+ String fwdRule = "";
+ String fwdLabel = "";
+ String revRuleKey = targetNodeType + "|" + startNodeType;
+ int revRuleCount = 0;
+ String revRule = "";
+ String revLabel = "";
+ String edRule = "";
+ String edLabel = "";
+
+ Boolean checkType = false;
+ if( (edgeType != null) && edgeType != "" ){
+ checkType = true;
+ }
+
+ // As of 16-07, it is possible to have more than one kind of edge defined between a given
+ // pair of nodeTypes. So we need to check to see if there is only one possibility, or if
+ // we need to look at the edgeType to determine which to use.
+ // NOTE -- we're only supporting having 2 edges between a given pair of nodeTypes and
+ // one and only one of them would have to be a parent-child edge.
+
+ if( DbEdgeRules.EdgeRules.containsKey(fwdRuleKey) ){
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(fwdRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ while( ruleItr.hasNext() ){
+ String tmpRule = ruleItr.next();
+ String [] rules = tmpRule.split(",");
+ String tmpLabel = rules[0];
+ String tmpParChild = rules[3];
+ if( !checkType
+ || (checkType && tmpParChild.equals("true") && edgeType.equals("parentChild"))
+ || (checkType && tmpParChild.equals("false") && edgeType.equals("cousin")) ){
+ // Either they didn't want us to check the edgeType or it is a match
+ fwdRuleCount++;
+ if( fwdRuleCount > 1 ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules found for nodeTypes: [" + startNodeType + "], ["
+ + targetNodeType + "], edgeType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else {
+ fwdRule = tmpRule;
+ fwdLabel = tmpLabel;
+ }
+ }
+ }
+ }
+
+ // Try it the other way also (unless this is the case of a nodeType recursively pointing to itself
+ // Ie. the edge rule: "model-element|model-element"
+ if( !revRuleKey.equals(fwdRuleKey) && DbEdgeRules.EdgeRules.containsKey(revRuleKey) ){
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(revRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ while( ruleItr.hasNext() ){
+ String tmpRule = ruleItr.next();
+ String [] rules = tmpRule.split(",");
+ String tmpLabel = rules[0];
+ String tmpParChild = rules[3];
+ if( !checkType
+ || (checkType && tmpParChild.equals("true") && edgeType.equals("parentChild"))
+ || (checkType && tmpParChild.equals("false") && edgeType.equals("cousin")) ){
+ // Either they didn't want us to check the edgeType or it is a match
+ revRuleCount++;
+ if( revRuleCount > 1 ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules found for nodeTypes: [" + targetNodeType + "], ["
+ + startNodeType + "], edgeType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else {
+ revRule = tmpRule;
+ revLabel = tmpLabel;
+ }
+ }
+ }
+ }
+
+ if( (fwdRuleCount == 1) && (revRuleCount == 0) ){
+ // We can use the node info in the order they were given
+ fromVtx = startVert;
+ toVtx = targetVert;
+ edRule = fwdRule;
+ edLabel = fwdLabel;
+ }
+ else if( (fwdRuleCount == 0) && (revRuleCount == 1) ){
+ // We need to switch the vertex order so the edge-direction is correct
+ toVtx = startVert;
+ fromVtx = targetVert;
+ edRule = revRule;
+ edLabel = revLabel;
+ }
+ else if( (fwdRuleCount == 0) && (revRuleCount == 0) ){
+ // No edge rule found for this
+ String detail = "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + targetNodeType
+ + "], checkLabelType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else if( (fwdRuleCount > 0) && (revRuleCount > 0) ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules (fwd and rev) found for nodeTypes: [" + startNodeType + "], ["
+ + targetNodeType + "], checkLabelType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ // If we got to this point, we now have a single edge label and we know to and from Vtx.
+
+ HashMap <String,Object> edgeParamHash = getEdgeTagPropPutHash4Rule(transId, fromAppId, edRule);
+ // We do "source-of-truth" for all edges
+ edgeParamHash.put("source-of-truth", fromAppId );
+
+ TitanEdge returnEdge = saveAaiEdgeToDb(transId, fromAppId, graph, edLabel, fromVtx, toVtx, edgeParamHash, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert ) throws AAIException{
+ return persistAaiEdge( transId, fromAppId, graph,
+ startVert, targetVert, null);
+ }
+ // End persistAaiEdge()
+
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ String edgeLabel, TitanVertex startVert, TitanVertex targetVert,
+ HashMap <String,Object> propHash, Boolean addIfNotFound ) throws AAIException{
+
+ /*----- This method is depricated ------
+ * We will ignore the parameters: edgeLabel, propHash and addIfNotFound
+ * We will use the remaining params to call the newer version of this method
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdge--Depricated--");
+
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, null);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End depricated version of persistAaiEdge()
+
+
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @param apiVersion the api version
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdgeWithDepParams");
+
+ TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion );
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End persistAaiEdgeWithDepParams()
+
+ // Version that lets you pass in an edgeType ("parentChild" or "cousin" since it sometimes cannot be determined
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @param apiVersion the api version
+ * @param edgeType the edge type
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ // from the two nodeTypes anymore (16-07)
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash,
+ String apiVersion, String edgeType) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdgeWithDepParams");
+
+ TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion );
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion, edgeType);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End persistAaiEdgeWithDepParams()
+
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash) throws AAIException{
+ return persistAaiEdgeWithDepParams( transId, fromAppId, graph,
+ startVert, targetNodeType, targetNodeParamHash, null);
+ }
+
+ /**
+ * Gets the node key prop hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param vtx the vtx
+ * @return nodeKeyPropHash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, Object> getNodeKeyPropHash( String transId, String fromAppId, TitanTransaction graph, TitanVertex vtx) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeKeyPropHash");
+
+ if( vtx == null ){
+ String emsg = "null node object passed to getNodeKeyPropHash().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg );
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ if( ! dbMaps.NodeKeyProps.containsKey(nType) ){
+ // Problem if no key Properties defined for this nodeType
+ logline.add("nodeType", nType);
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "No node-key-properties defined in dbMaps for nodeType = " + nType + " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ HashMap <String,Object>nodeKeyPropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(nType);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ Object value = (Object) vtx.<Object>property(propName).orElse(null);
+ nodeKeyPropsHash.put(propName, value);
+ }
+
+ //aaiLogger.debug(logline, " end ");
+ return nodeKeyPropsHash;
+
+ }// End of getNodeKeyPropHash()
+
+ /**
+ * Gets the node name prop hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param vtx the vtx
+ * @param apiVersion the api version
+ * @return nodeKeyPropHash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, Object> getNodeNamePropHash( String transId, String fromAppId, TitanTransaction graph, TitanVertex vtx, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeNamePropHash");
+
+ if( vtx == null ){
+ String emsg = "null node object passed to getNodeNamePropHash().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg );
+ }
+
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ HashMap <String,Object>nodeNamePropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = DbMeth.getNodeNameProps(transId, fromAppId, nType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ Object value = (Object) vtx.<Object>property(propName).orElse(null);
+ nodeNamePropsHash.put(propName, value);
+ }
+
+ //aaiLogger.debug(logline, " end ");
+ return nodeNamePropsHash;
+
+ }// End of getNodeNamePropHash()
+
+
+ /**
+ * Removes the aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param tEdge the t edge
+ * @return void
+ */
+ public static void removeAaiEdge( String transId, String fromAppId, TitanTransaction graph, TitanEdge tEdge){
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "removeAaiEdge");
+
+ // Before removing the edge, touch the vertices on each side so their resource-versions will get updated
+ TitanVertex tmpVIn = tEdge.inVertex();
+ touchVertex( transId, fromAppId, tmpVIn );
+
+ TitanVertex tmpVOut = tEdge.outVertex();
+ touchVertex( transId, fromAppId, tmpVOut );
+
+ // Remove the passed in edge.
+ tEdge.remove();
+ aaiLogger.info(logline, true, "0");
+
+ }// end of removeAaiEdge()
+
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @param resourceVersion the resource version
+ * @throws AAIException the AAI exception
+ */
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion, String resourceVersion ) throws AAIException{
+ // Note: the resource Version Override flag is only set to true when called by the Model Delete code which
+ // has no way to know the resource-versions of nodes at lower-levels of it's model topology.
+ Boolean resVersionOverrideFlag = false;
+ removeAaiNode( transId, fromAppId, graph, thisVtx, scopeParam, apiVersion, resourceVersion, resVersionOverrideFlag );
+ }
+
+
+ /**
+ * <pre>
+ * Possible values for deleteScope can be:
+ * USE_DEFAULT - Get the scope from ref data for this node
+ * THIS_NODE_ONLY (but should fail if it there are nodes that depend on it for uniqueness)
+ * CASCADE_TO_CHILDREN - will look for OUT-Edges that have parentOf/hasDelTarget = true and follow those down
+ * ERROR_4_IN_EDGES_OR_CASCADE - combo of error-if-any-IN-edges + CascadeToChildren
+ * ERROR_IF_ANY_IN_EDGES - Fail if this node has any existing IN edges
+ * ERROR_IF_ANY_EDGES - Fail if this node has any existing edges at all!
+ * </pre>.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @param resourceVersion the resource version
+ * @param resVerOverride the res ver override
+ * @return void
+ * @throws AAIException the AAI exception
+ */
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion, String resourceVersion, Boolean resVerOverride ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "removeAaiNode");
+ logline.add("scopeParam", scopeParam);
+
+ String nodeType2Del = thisVtx.<String>property("aai-node-type").orElse(null);
+ String deleteScope = scopeParam;
+ if( scopeParam.equals("USE_DEFAULT") ){
+ deleteScope = getDefaultDeleteScope(transId, fromAppId, nodeType2Del, apiVersion);
+ logline.add("deleteScope", deleteScope);
+ }
+
+ if( !resVerOverride && needToDoResourceVerCheck(apiVersion, false) ){
+ // Need to check that they knew what they were deleting
+ String existingResVer = thisVtx.<String>property("resource-version").orElse(null);
+ if( resourceVersion == null || resourceVersion.equals("") ){
+ aaiLogger.info(logline, false, "AAI_6130");
+ String detail = "Resource-version not passed for delete of = " + nodeType2Del;
+ throw new AAIException("AAI_6130", detail);
+ }
+ else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version MISMATCH for delete of = " + nodeType2Del;
+ throw new AAIException("AAI_6131", detail);
+ }
+ }
+
+ if( !deleteScope.equals("THIS_NODE_ONLY")
+ && !deleteScope.equals("CASCADE_TO_CHILDREN")
+ && !deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE")
+ && !deleteScope.equals("ERROR_IF_ANY_EDGES")
+ && !deleteScope.equals("ERROR_IF_ANY_IN_EDGES") ){
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = " Unrecognized value in deleteScope: [" + deleteScope + "].";
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ if( deleteScope.equals("ERROR_IF_ANY_EDGES") ){
+ if ( thisVtx.edges(Direction.BOTH).hasNext() ) {
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = " Node cannot be deleted because it still has Edges and the ERROR_IF_ANY_EDGES scope was used.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ else if( deleteScope.equals("ERROR_IF_ANY_IN_EDGES") || deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE") ){
+ Iterator <Edge> eI = thisVtx.edges(Direction.IN);
+ boolean onlyHasParent = false;
+ Edge temp = null;
+ if( eI != null && eI.hasNext() ){
+ temp = eI.next();
+ Boolean isParent = temp.<Boolean>property("isParent").orElse(null);
+ if (isParent != null && isParent && !eI.hasNext()) {
+ onlyHasParent = true;
+ }
+
+ if (!onlyHasParent) {
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = " Node cannot be deleted because it still has Edges and the " + deleteScope + " scope was used.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ }
+ else if( deleteScope.equals("THIS_NODE_ONLY")){
+ // Make sure nobody depends on this node.
+ Iterator<Edge> eI = thisVtx.edges(Direction.BOTH);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(thisVtx);
+ String nodeTypeA = otherVtx.<String>property("aai-node-type").orElse(null);
+ if( nodeTypeACanDependOnB(transId, fromAppId, nodeTypeA, nodeType2Del, apiVersion)){
+ // We're only supposed to delete this node - but another node is dependant on it,
+ // so we shouldn't delete this one.
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = " Node cannot be deleted using scope = " + deleteScope +
+ " another node (type = " + nodeTypeA + ") depends on it for uniqueness.";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ }
+
+ // We've passed our checks - so do some deleting of edges and maybe pass
+ // the delete request down to children or delete-targets.
+
+ // First we deal with the "IN"-Edges which can't have children/delete-targets which
+ // by definition (of "IN") on the other end
+ Iterator <Edge> eI_In = thisVtx.edges(Direction.IN);
+ while( eI_In.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI_In.next();
+
+ //- "touch" vertex on other side of this edge so it gets a fresh resource-version
+ TitanVertex tmpVOther = ed.otherVertex(thisVtx);
+ touchVertex( transId, fromAppId, tmpVOther );
+
+ ed.remove();
+ }
+
+ // Now look at the "OUT"-edges which might include children or delete-targets
+ String cascadeMsg = "This nt = " + nodeType2Del + ", Cascading del to: ";
+ Iterator <Edge> eI_Out = thisVtx.edges(Direction.OUT);
+ if( !eI_Out.hasNext() ){
+ cascadeMsg = cascadeMsg + "[no children for this node]";
+ }
+ while( eI_Out.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI_Out.next();
+
+ // "touch" vertex on other side of this edge so it gets a fresh resource-version
+ TitanVertex tmpVOther = ed.otherVertex(thisVtx);
+ touchVertex( transId, fromAppId, tmpVOther );
+
+ Boolean otherVtxAChild = ed.<Boolean>property("isParent").orElse(null);
+ if( otherVtxAChild == null ){
+ otherVtxAChild = false;
+ }
+
+ Boolean otherVtxADeleteTarget = ed.<Boolean>property("hasDelTarget").orElse(null);
+ if( otherVtxADeleteTarget == null ){
+ otherVtxADeleteTarget = false;
+ }
+
+ if( (otherVtxAChild || otherVtxADeleteTarget) &&
+ (deleteScope.equals("CASCADE_TO_CHILDREN") || deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE")) ){
+ // Delete the edge to the child and Pass the delete down to it.
+ ed.remove();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(thisVtx);
+ String vid = otherVtx.id().toString();
+ String nty = otherVtx.<String>property("aai-node-type").orElse(null);
+ String resVers = otherVtx.<String>property("resource-version").orElse(null);
+ cascadeMsg = cascadeMsg + "[" + nty + ":" + vid + "]";
+ removeAaiNode(transId, fromAppId, graph, otherVtx, "CASCADE_TO_CHILDREN", apiVersion, resVers);
+ }
+ else {
+ // The other node is not a child or deleteTarget. Delete the edge to it if it is not
+ // dependent (Should never be dependent since it's not a child/delTarget... but
+ // someone could create a node that was dependent for Uniqueness without
+ // being a child/target.
+
+ // DEBUG -- eventually add the check for dependancy that isn't on a parent-type or delTarget-type edge
+ ed.remove();
+ }
+ }
+ logline.add("cascadeMsg",cascadeMsg);
+
+ Iterator<Edge> eI = thisVtx.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ // By this point, either there were no edges to deal with, or we have dealt with them.
+ thisVtx.remove();
+ }
+ else {
+ // Something went wrong and we couldn't delete all the edges for this guy.
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = "Node could be deleted because it unexpectedly still has Edges.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ aaiLogger.info(logline, true, "0");
+
+ }
+
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @return void
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam) throws AAIException{
+ removeAaiNode(transId, fromAppId, graph, thisVtx, scopeParam, null, null);
+ }
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion ) throws AAIException{
+ removeAaiNode(transId, fromAppId, graph, thisVtx, scopeParam, apiVersion, null);
+ }
+ // end of removeAaiNode()
+
+
+ /**
+ * Delete all graph data.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @return void
+ */
+ public static void deleteAllGraphData( String transId, String fromAppId, TitanGraph graph ){
+ /** ======================================================================
+ * WARNING -- this removes ALL the data that is currently in the graph.
+ * ======================================================================
+ **/
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deleteAllGraphData");
+ Iterator<Edge> edges = graph.edges(Direction.BOTH);
+ graph.tx().commit();
+ Edge edge = null;
+ while (edges.hasNext()) {
+ edge = edges.next();
+ edges.remove();
+ }
+ graph.tx().commit();
+ Iterator<Vertex> vertices = graph.vertices();
+ graph.tx().commit();
+ Vertex vertex = null;
+ while (vertices.hasNext()) {
+ vertex = vertices.next();
+ vertex.remove();
+ }
+ graph.tx().commit();
+ aaiLogger.info(logline, true, "0");
+ }
+
+
+ /**
+ * Show all edges for node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @return the array list
+ */
+ public static ArrayList <String> showAllEdgesForNode( String transId, String fromAppId, TitanVertex tVert ){
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+ Iterator <Edge> eI = tVert.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ retArr.add("No edges were found for this vertex. ");
+ }
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ String lab = ed.label();
+ TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert);
+ if( vtx == null ){
+ retArr.add(" >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
+ }
+ else {
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ String vid = vtx.id().toString();
+ retArr.add("Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid );
+ //DEBUG ---
+ //showPropertiesForEdge( transId, fromAppId, ed );
+ }
+ }
+ return retArr;
+ }
+
+
+ /**
+ * Show properties for node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @return the array list
+ */
+ public static ArrayList <String> showPropertiesForNode( String transId, String fromAppId, TitanVertex tVert ){
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+ if( tVert == null ){
+ retArr.add("null Node object passed to showPropertiesForNode()\n");
+ }
+ else {
+ String nodeType = "";
+ //String datType = "";
+ Object ob = tVert.<Object>property("aai-node-type").orElse(null);
+ if( ob == null ){
+ nodeType = "null";
+ }
+ else{
+ nodeType = ob.toString();
+ //datType = ob.getClass().getSimpleName();
+ }
+
+ retArr.add(" AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
+ retArr.add(" Property Detail: ");
+ Iterator<VertexProperty<Object>> pI = tVert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ Object val = tp.value();
+ //retArr.add("Prop: [" + tp.getPropertyKey() + "], val = [" + val + "], dataType = " + val.getClass() );
+ retArr.add("Prop: [" + tp.key() + "], val = [" + val + "] ");
+ }
+ }
+ return retArr;
+ }
+
+
+ /**
+ * Gets the node name props.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeNameProps( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeNameProps");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> nameProps = new ArrayList <String>();
+ if( dbMaps.NodeNameProps.containsKey(nodeType) ){
+ nameProps = dbMaps.NodeNameProps.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, theoretically, all the guys in the same
+ // category should have the same name property -- so if they just give us the category, we will
+ // just give the name info from the first nodeType we encounter of that category.
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType;
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String nodeTypesString = flds[0];
+ String [] nodeTypeNames = nodeTypesString.split("\\|");
+ if( nodeTypeNames != null && nodeTypeNames.length > 0 ){
+ // We'll just use the first one
+ String nt = nodeTypeNames[0];
+ nameProps = dbMaps.NodeNameProps.get(nt);
+ }
+ }
+
+
+ // Note - it's ok if there was no defined name property for this nodeType.
+
+ return nameProps;
+
+ }// end of getNodeKeyPropNames
+
+
+ /**
+ * Gets the edge tag prop put hash 4 rule.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param edRule the ed rule
+ * @return the edge tag prop put hash 4 rule
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getEdgeTagPropPutHash4Rule( String transId, String fromAppId, String edRule )
+ throws AAIException{
+ // For a given edgeRule - already pulled out of DbEdgeRules.EdgeRules -- parse out the "tags" that
+ // need to be set for this kind of edge.
+ // These are the Boolean properties like, "isParent", "usesResource" etc.
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getEdgeTagPropPutHash4Rule");
+
+ HashMap <String,Object> retEdgePropPutMap = new HashMap <String,Object>();
+
+ if( (edRule == null) || edRule.equals("") ){
+ // No edge rule found for this
+ String detail = " blank edRule passed to getEdgeTagPropPutHash4Rule() ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ int tagCount = DbEdgeRules.EdgeInfoMap.size();
+ String [] rules = edRule.split(",");
+ if( rules.length != tagCount ){
+ String detail = "Bad EdgeRule data (itemCount =" + rules.length + ") for rule = [" + edRule + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ // In DbEdgeRules.EdgeRules -- What we have as "edRule" 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
+ // tags as defined in EdgeInfoMap.
+ // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it
+ for( int i = DbEdgeRules.firstTagIndex; i < tagCount; i++ ){
+ String booleanStr = rules[i];
+ Integer mapKey = new Integer(i);
+ String propName = DbEdgeRules.EdgeInfoMap.get(mapKey);
+ String revPropName = propName + "-REV";
+
+ if( booleanStr.equals("true") ){
+ retEdgePropPutMap.put(propName, true);
+ retEdgePropPutMap.put(revPropName,false);
+ }
+ else if( booleanStr.equals("false") ){
+ retEdgePropPutMap.put(propName, false);
+ retEdgePropPutMap.put(revPropName,false);
+ }
+ else if( booleanStr.equals("reverse") ){
+ retEdgePropPutMap.put(propName, false);
+ retEdgePropPutMap.put(revPropName,true);
+ }
+ else {
+ String detail = "Bad EdgeRule data for rule = [" + edRule + "], val = [" + booleanStr + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ }
+
+ return retEdgePropPutMap;
+
+ } // End of getEdgeTagPropPutHash()
+
+
+
+ /**
+ * Gets the edge tag prop put hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param edgeRuleKey the edge rule key
+ * @return the edge tag prop put hash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getEdgeTagPropPutHash( String transId, String fromAppId, String edgeRuleKey )
+ throws AAIException{
+ // For a given edgeRuleKey (nodeTypeA|nodeTypeB), look up the rule that goes with it in
+ // DbEdgeRules.EdgeRules and parse out the "tags" that need to be set on each edge.
+ // These are the Boolean properties like, "isParent", "usesResource" etc.
+ // Note - this code is also used by the updateEdgeTags.java code
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getEdgeTagPropPutHash");
+
+ if( ! DbEdgeRules.EdgeRules.containsKey(edgeRuleKey) ){
+ String detail = "Could not find an DbEdgeRule entry for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + ".";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ String edRule = "";
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For the current database, there can only be one type of edge between any two particular node-types.
+ // DEBUG ------------------- TBD -------------
+ // WARNING --- THIS IS NOT TRUE ANYMORE (16-07) ---- WARNING
+
+ edRule = ruleItr.next();
+ }
+ else {
+ // No edge rule found for this
+ String detail = "Could not find an EdgeRule for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + ".";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ HashMap <String,Object> retEdgePropPutMap = getEdgeTagPropPutHash4Rule(transId, fromAppId, edRule);
+
+ return retEdgePropPutMap;
+
+ } // End of getEdgeTagPropPutHash()
+
+
+ /**
+ * This property was put by newer version of code.
+ *
+ * @param apiVersionStr the api version str
+ * @param nodeType the node type
+ * @param propName the prop name
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private static boolean thisPropertyWasPutByNewerVersionOfCode( String apiVersionStr,
+ String nodeType, String propName) throws AAIException{
+ // We want to return True if the nodeType + property-name combo was introduced AFTER the apiVersion passed.
+
+ int apiVerInt = 0;
+ int propIntroVerInt = 0;
+
+ if( apiVersionStr == null || apiVersionStr.equals("") ){
+ apiVersionStr = org.openecomp.aai.util.AAIApiVersion.get();
+ }
+ apiVerInt = getVerNumFromVerString(apiVersionStr);
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ String propIntroKey = nodeType + "|" + propName;
+ if( propName.equals("prov-status") ){
+ // This is a special case -- The dbMaps from v2 has it in there, but it was introduced half way through. So
+ // it needs to be catogorized as v3.
+ propIntroVerInt = 3;
+ }
+ else if( ! dbMaps.PropertyVersionInfoMap.containsKey(propIntroKey) ){
+ String detail = propIntroKey + " [" + propIntroKey + "] not found in dbMaps.PropertyVersionInfoMap.";
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ String propIntroVerString = dbMaps.PropertyVersionInfoMap.get(propIntroKey);
+ propIntroVerInt = getVerNumFromVerString( propIntroVerString );
+ }
+
+ if( propIntroVerInt > apiVerInt ){
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ } // End of thisPropertyWasPutByNewerVersionOfCode()
+
+
+ /**
+ * Touch vertex.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param v the v
+ * @return void
+ */
+ public static void touchVertex( String transId, String fromAppId, TitanVertex v ){
+ // We want to "touch" the vertex -- Ie. update it's last-mod-date, last-mod- resource-version to the current date/time
+ if( v != null ){
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ String timeNowInSec = "" + unixTimeNow;
+ v.property( "aai-last-mod-ts", timeNowInSec );
+ v.property( "resource-version", timeNowInSec );
+ v.property( "last-mod-source-of-truth", fromAppId );
+ }
+ } // End of touchVertex()
+
+
+ /**
+ * Check prop cardinality.
+ *
+ * @param propName the prop name
+ * @param cardinalityType the cardinality type
+ * @return boolean
+ * @throws AAIException the AAI exception
+ */
+ public static boolean checkPropCardinality( String propName, String cardinalityType ) throws AAIException {
+
+ // Return true if the named property is tagged in our dbMaps PropetyDataTypeMap as
+ // having the passed in cardinality type.
+ // NOTE: supported cardinality types in dbMaps = "Set" or "List"
+ // In Titan, those go in as "SET" and "LIST"
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ if( dbMaps.PropertyDataTypeMap.containsKey(propName) ){
+ String propDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if( propDataType != null && propDataType.startsWith(cardinalityType) ){
+ return true;
+ }
+ }
+ return false;
+
+ } // End of checkPropCardinality()
+
+ /**
+ * Convert type if needed.
+ *
+ * @param propName the prop name
+ * @param val the val
+ * @return convertedValue (if it was a String but needed to be a Boolean)
+ * @throws AAIException the AAI exception
+ */
+ public static Object convertTypeIfNeeded( String propName, Object val )
+ throws AAIException {
+ // Make sure the dataType of the passed-in Object matches what the DB expects
+
+ // NOTE: since this is a fix very late in our dev cycle, we'll just fix the scenarios that
+ // we're having trouble with which is Strings getting into the db which should be going in as
+ // Booleans or Integers.
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ if( dbMaps.PropertyDataTypeMap.containsKey(propName) ){
+ String dbExpectedDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if( dbExpectedDataType != null
+ && dbExpectedDataType.equals("Boolean")
+ && val != null
+ && !(val instanceof Boolean) ){
+ String valStr = val.toString().trim();
+ if( valStr.equals("true") || valStr.equals("True") || valStr.equals("TRUE") ){
+ return Boolean.valueOf("true");
+ }
+ else if( valStr.equals("false") || valStr.equals("False") || valStr.equals("FALSE") ){
+ return Boolean.valueOf("false");
+ }
+ else {
+ String emsg = "Error trying to convert value: [" + valStr + "] to a Boolean for property + " + propName + "\n";
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ else if( dbExpectedDataType != null
+ && dbExpectedDataType.equals("Integer")
+ && val != null
+ && !(val.toString().trim().equals(""))
+ && !(val instanceof Integer) ){
+ String valStr = val.toString().trim();
+ Integer newInt;
+ try {
+ newInt = Integer.valueOf(valStr);
+ return newInt;
+ }
+ catch( Exception e ){
+ String emsg = "Error trying to convert value: [" + valStr + "] to an Integer for property + " + propName + "\n";
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ }
+
+ // If it didn't need to be converted, just return it.
+ return val;
+
+ } // End of convertTypeIfNeeded()
+
+
+
+ /**
+ * This vertex not reachable.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ */
+ public static boolean thisVertexNotReachable( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version){
+ if( v == null ){
+ return true;
+ }
+ else {
+ try {
+ v.id().toString();
+ }
+ catch( Exception ex ){
+ // Could not get this -- sometimes we're holding a vertex object that has gotten deleted, so
+ // when we try to get stuff from it, we get an "Element Has Been Removed" error from Titan
+ return true;
+ }
+ }
+
+ return false;
+
+ } // End of thisVertexNotReachable()
+
+ /**
+ * This vertex has bad edges.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ */
+ public static boolean thisVertexHasBadEdges( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version){
+
+ Iterator <Edge> eItor = v.edges(Direction.BOTH);
+ while( eItor.hasNext() ){
+ Edge e = null;
+ e = eItor.next();
+ if( e == null ){
+ return true;
+ }
+ Vertex vIn = e.inVertex();
+ if( (vIn == null) || (vIn.<String>property("aai-node-type").orElse(null) == null) ){
+ // this is a bad edge because it points to a vertex that isn't there anymore
+ return true;
+ }
+
+ Vertex vOut = e.outVertex();
+ if( (vOut == null) || (vOut.<String>property("aai-node-type").orElse(null) == null) ){
+ // this is a bad edge because it points to a vertex that isn't there anymore
+ return true;
+ }
+ }
+
+ // If we made it to here, the vertex's edges must be ok.
+ return false;
+
+ } // End of thisVertexHasBadEdges()
+
+
+ /**
+ * This vertex is A phantom.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ * @throws AAIException the AAI exception
+ */
+ public static boolean thisVertexIsAPhantom( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version )
+ throws AAIException {
+
+
+ // The kind of Phantom we're looking for is the kind that we sometimes get when we do a select without
+ // using key properties. They can be in the database as a vertex, but the indexes that should point to
+ // them are not working -- so they cannot be used by normal interfaces (like the REST API) which means
+ // that if we return it, it can mess up a caller who tries to use it.
+ if( v == null ){
+ return true;
+ }
+ String thisVid = v.id().toString();
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Object propOb = v.<Object>property("aai-node-type").orElse(null);
+ if( propOb == null ){
+ // This vertex does not have an aai-node-type ---> it is messed up
+ return true;
+ }
+ String nType = propOb.toString();
+ if( ! dbMaps.NodeKeyProps.containsKey(nType) ){
+ // This node Type does not have keys defined
+ // This could just be bad reference data, so we will not flag this guy, but we
+ // can't really do our test...
+ return false;
+ }
+
+ HashMap <String,Object> propHashWithKeys = new HashMap<String, Object>();
+ Collection <String> keyProps = null;
+ try {
+ keyProps = getNodeKeyPropNames(transId, fromAppId, nType, version);
+ }
+ catch (AAIException ex) {
+ // something wrong with getting this guy's key property names - we'll abandon this test...
+ return false;
+ }
+
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ String propVal = "";
+ Object ob = v.<Object>property(propName).orElse(null);
+ if( ob != null ){
+ propVal = ob.toString();
+ }
+ propHashWithKeys.put(propName, propVal);
+ }
+ try {
+ // Note - We can get more than one back since some nodes need a dep. node for uniqueness.
+ // We don't care about that -- we just want to make sure we can get this vertex back when
+ // we're searching with it's indexed fields.
+ // NOTE - we're passing the skipGroomCheck to getNodes so we don't wind up in an infinite loop
+ ArrayList <TitanVertex> vertList2 = getNodes( transId, fromAppId, graph, nType, propHashWithKeys, false, version, true );
+ Iterator<TitanVertex> iter2 = vertList2.iterator();
+ while( iter2.hasNext() ){
+ TitanVertex tvx2 = iter2.next();
+ String foundId = tvx2.id().toString();
+ if( foundId.equals( thisVid ) ){
+ // We could get back the vertex by looking it up using key properties... That's good.
+ return false;
+ }
+ }
+ }
+ catch (Exception e2) {
+ //String msg = " Error encountered for this vertex id: [" + thisVid +
+ // "]. Caught this exception: " + e2.toString();
+ // Something messed up - but that doesn't prove that this is a phantom.
+ return false;
+ }
+
+ // If we dropped down to here, we have looked but could not pull the vertex out of the
+ // db using it's key fields, so it gets flagged as a Phantom.
+ return true;
+
+ } // End of thisVertexIsAPhantom()
+
+
+ /**
+ * Gets the node by unique key.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param aaiUniquekey the aai uniquekey
+ * @return the node by unique key
+ */
+ public TitanVertex getNodeByUniqueKey(String transId, String fromAppId, TitanTransaction graph, String aaiUniquekey) {
+
+ TitanVertex vert = null;
+
+ Iterator<?> vertI = graph.query().has("aai-unique-key", aaiUniquekey).vertices().iterator();
+
+ if( vertI != null && vertI.hasNext()) {
+ // We found a vertex that meets the input criteria.
+ vert = (TitanVertex) vertI.next();
+ }
+
+ return vert;
+ }
+
+
+
+}
+