aboutsummaryrefslogtreecommitdiffstats
path: root/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java
diff options
context:
space:
mode:
Diffstat (limited to 'ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java')
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java3490
1 files changed, 3490 insertions, 0 deletions
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java
new file mode 100644
index 0000000..7b9f031
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java
@@ -0,0 +1,3490 @@
+/*-
+ * ============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.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+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.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.SimpleTimeLimiter;
+import com.google.common.util.concurrent.TimeLimiter;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+/**
+ * Utility class that uses Model/Named-Query definitions to navigate the graph.
+ */
+public class ModelBasedProcessing{
+
+ private static AAILogger aaiLogger = new AAILogger(ModelBasedProcessing.class.getName());
+ private static int maxLevels = 50; // max depth allowed for our model - to protect against infinite loop problems
+
+
+
+ /**
+ * Gets the start nodes and models.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param passedModelNameVersionId the passed model name version id -- optional (unique id for a model)
+ * @param passedModelId the passed model id -- optional
+ * @param passedModelName the passed model name
+ * @param passedTopNodeType the passed top node type -- optional (needed if neither model-id nor model-name-version-id is passed)
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
+ * @param apiVer the api ver
+ * @return List of TitanVertex's
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> getStartNodesAndModels( String transId, String fromAppId, TitanTransaction graph,
+ String passedModelNameVersionId,
+ String passedModelId,
+ String passedModelName,
+ String passedTopNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getStartNodesAndModels");
+
+
+ // ----------------------------------------------------------------------------------------------------
+ // Get a hash for all start-nodes (key = vtxId, val = modelNameVersionId that applies)
+ // If no start-node-key info is passed, then use either the passed modelNameVersionId or
+ // the passed model-id or model-name to collect them.
+ // If start-node-key info is given, use it instead to look for start-nodes.
+ // Note: if ONLY start-node-key info is given, then it would have to map to nodes which
+ // have persona data. Otherwise we'd have no way to know what model to collect data with.
+ // ----------------------------------------------------------------------------------------------------
+
+ Iterable <?> startVerts = null;
+ HashMap <String, String> startVertInfo = new HashMap <String,String> ();
+ if( startNodeFilterArrayOfHashes.isEmpty() ){
+ // Since they did not give any data to find start instances, we will have to find them
+ // using whatever model-info they provided so we can use it to map to persona-data in the db.
+ if( (passedModelNameVersionId == null || passedModelNameVersionId.equals(""))
+ && (passedModelId == null || passedModelId.equals(""))
+ && (passedModelName == null || passedModelName.equals(""))){
+ String emsg = "ModelId or ModelName or ModelNameVersionId required if no startNodeFilter data passed. \n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+ else {
+ // Use whatever model info they pass to find start-node instances
+ // Get the first/top named-query-element used by this query
+ if( passedModelNameVersionId != null && !passedModelNameVersionId.equals("") ){
+ // Need to look up the model-id and model-version to check against persona data
+ TitanVertex modVtx = getModelUsingUUID( transId, fromAppId, graph, passedModelNameVersionId );
+ String calcModId = modVtx.<String>property("model-id").orElse(null);
+ String calcModVer = modVtx.<String>property("model-version").orElse(null);
+ // Now we can look up instances that match this model's info
+ startVerts = graph.query().has("persona-model-id",calcModId).has("persona-model-version",calcModVer).vertices();
+ }
+ else if( passedModelId != null && !passedModelId.equals("") ){
+ // They gave us the model-id
+ startVerts = graph.query().has("persona-model-id",passedModelId).vertices();
+ }
+ else if( passedModelName != null && !passedModelName.equals("") ){
+ ArrayList <TitanVertex> modelVtxList = getModelsUsingName(transId, fromAppId, graph, passedModelName);
+ ArrayList <TitanVertex> startVtxList = new ArrayList <TitanVertex> ();
+ // Need to look up the model-ids and model-versions to check against persona data
+ if( !modelVtxList.isEmpty() ){
+ for( int i = 0; i < modelVtxList.size(); i++ ){
+ String calcModId = (modelVtxList.get(i)).<String>property("model-id").orElse(null);
+ String calcModVer = (modelVtxList.get(i)).<String>property("model-version").orElse(null);
+ // Now we can look up instances that match this model's info
+ Iterable <?> tmpStartVerts = graph.query().has("persona-model-id",calcModId).has("persona-model-version",calcModVer).vertices();
+ Iterator <?> tmpStartIter = tmpStartVerts.iterator();
+ while( tmpStartIter.hasNext() ){
+ TitanVertex tmpStartVert = (TitanVertex) tmpStartIter.next();
+ startVtxList.add(tmpStartVert);
+ }
+ }
+ }
+ if( !startVtxList.isEmpty() ){
+ startVerts = startVtxList;
+ }
+ }
+ }
+
+ if( startVerts != null ){
+ Iterator <?> startVertsIter = startVerts.iterator();
+ while( startVertsIter.hasNext() ){
+ TitanVertex tmpStartVert = (TitanVertex) startVertsIter.next();
+ String vid = tmpStartVert.id().toString();
+ String tmpModId = tmpStartVert.<String>property("persona-model-id").orElse(null);
+ String tmpModVers = tmpStartVert.<String>property("persona-model-version").orElse(null);
+ String calcModNameVersId = getModNameVerId( transId, fromAppId, graph, tmpModId, tmpModVers );
+ startVertInfo.put(vid, calcModNameVersId);
+ }
+ }
+ if( startVertInfo.isEmpty() ){
+ String emsg = "Start Node(s) could not be found for model data passed. " +
+ "(modelNameVersionId = [" + passedModelNameVersionId +
+ "], modelId = [" + passedModelId +
+ "], modelName = [" + passedModelName +
+ "])\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+ }
+ else {
+ // Use start-node filter info to find start-node(s) - Note - there could also be model info passed that we'll need
+ // to use to trim down the set of start-nodes that we find based on the startNodeFilter data.
+ String modTopNodeType ="";
+ String modInfoStr = "";
+ if( passedModelNameVersionId != null && !passedModelNameVersionId.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph, passedModelNameVersionId, "", "" );
+ modInfoStr = "modelNameVersionId = (" + passedModelNameVersionId + ")";
+ }
+ else if( passedModelId != null && !passedModelId.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph,"", passedModelId, "" );
+ modInfoStr = "modelId = (" + passedModelId + ")";
+ }
+ else if( passedModelName != null && !passedModelName.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph,"", "", passedModelName );
+ modInfoStr = "modelName = (" + passedModelName + ")";
+ }
+
+ if( modTopNodeType.equals("") ){
+ if( (passedTopNodeType == null) || passedTopNodeType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for this request. modelInfo: [" + modInfoStr + "]";
+ throw new AAIException("AAI_6118", msg);
+ }
+ else {
+ // We couldn't find a top-model-type based on passed in model info, but they
+ // gave us a type to use -- so use it.
+ modTopNodeType = passedTopNodeType;
+ }
+ }
+ else {
+ // we did get a topNode type based on model info - make sure it doesn't contradict
+ // the passsed-in one (if there is one)
+ if( passedTopNodeType != null && !passedTopNodeType.equals("")
+ && !passedTopNodeType.equals(modTopNodeType) ){
+ String emsg = "topNodeType passed in [" + passedTopNodeType
+ + "] does not match nodeType derived for model info passed in: ["
+ + modTopNodeType + "]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+
+ ArrayList <String> modelNameVersionIds2Check = new ArrayList <String> ();
+ if( (passedModelName != null && !passedModelName.equals("")) ){
+ // They passed a modelName, so find all the model UUIDs (model-name-version-id's) that map to this
+ modelNameVersionIds2Check = getModelUuidsUsingName(transId, fromAppId, graph, passedModelName);
+ }
+ if( (passedModelNameVersionId != null && !passedModelNameVersionId.equals("")) ){
+ // They passed in a modelNameVersionId
+ if( modelNameVersionIds2Check.isEmpty() ){
+ // There was no modelName passed, so we can use the passed modelNameVersionId
+ modelNameVersionIds2Check.add(passedModelNameVersionId);
+ }
+ else if( modelNameVersionIds2Check.contains(passedModelNameVersionId) ){
+ // The passed in uuid does not conflict with what we got using the passed-in modelName.
+ // We'll just use the passed in uuid in this case.
+ // Hopefully they would not be passing strange combinations like this, but we'll try to deal with it.
+ modelNameVersionIds2Check = new ArrayList <String> (); // Clear out what we had
+ modelNameVersionIds2Check.add(passedModelNameVersionId);
+ }
+ }
+
+ // We should now be OK with our topNodeType for this request, so we can look for the actual startNodes
+ for( int i=0; i < startNodeFilterArrayOfHashes.size(); i++ ){
+ // Locate the starting node which will be used to look which corresponds to this set of filter data
+ TitanVertex startVtx = null;
+ try {
+ startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ modTopNodeType, startNodeFilterArrayOfHashes.get(i), apiVer );
+ }
+ catch( AAIException e ){
+ String msg = "Could not find startNode of type = [" + modTopNodeType + "], given these params: "
+ + startNodeFilterArrayOfHashes.get(i) + ". msg # from getUniqueNode() = " + e.getMessage();
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String vid = startVtx.id().toString();
+ String personaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ String personaModId = startVtx.<String>property("persona-model-id").orElse(null);
+
+ // Either this start-node has persona info (which should not contradict any passed-in model info)
+ // or they should have passed in the model to use - so we'd just use that.
+ if( personaModVersion != null && !personaModVersion.equals("") ){
+ // There is persona data in this start-node. So make sure it doesn't contradict any "passed" stuff
+ // Find out what modelNameVersionId that maps to
+ String personaModelNameVerId = getModNameVerId(transId, fromAppId, graph, personaModId, personaModVersion);
+
+ if( modelNameVersionIds2Check.isEmpty()
+ && (passedModelId == null || passedModelId.equals("")) ){
+ // They didn't pass any model info, so use the persona one.
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ else if( modelNameVersionIds2Check.isEmpty()
+ && (passedModelId != null && !passedModelId.equals("")) ){
+ // They passed in just the modelId - so check it
+ if( passedModelId.equals(personaModId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ else if( !modelNameVersionIds2Check.isEmpty()
+ && (passedModelId == null || passedModelId.equals("")) ){
+ // They passed in modelNameVersionId - so check
+ if( modelNameVersionIds2Check.contains(personaModelNameVerId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ else if( !modelNameVersionIds2Check.isEmpty()
+ && (passedModelId != null && !passedModelId.equals("")) ){
+ // We have BOTH a modelNameVersionIds and a modelId to check
+ if( passedModelId.equals(personaModId)
+ && modelNameVersionIds2Check.contains(personaModelNameVerId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ }
+ else {
+ // This start node did not have persona info -- so we will use the passed in model info if they passed one
+ if( passedModelNameVersionId.equals("") ){
+ String emsg = "Found startNode but no model info passed in and no persona model info in the start node.";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ startVertInfo.put(vid, passedModelNameVersionId);
+ }
+ }
+ }
+ }
+
+ return startVertInfo;
+
+ }//end of getStartNodesAndModels()
+
+
+ /**
+ * Query by model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id -- optional - (unique id for a model)
+ * @param modelId the model id -- optional
+ * @param modelName the model name
+ * @param topNodeType - optional (needed if neither model-id nor model-name-version-id is passed)
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByModel( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId,
+ String modelId,
+ String modelName,
+ String topNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ final String transId_f = transId;
+ final String fromAppId_f = fromAppId;
+ final TitanTransaction graph_f = graph;
+ final String modelNameVersionId_f = modelNameVersionId;
+ final String modelId_f = modelId;
+ final String modelName_f = modelName;
+ final String topNodeType_f = topNodeType;
+ final ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
+ final String apiVer_f = apiVer;
+
+ // Find out what our time-limit should be
+ int timeLimitSec = 0;
+ String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
+ if( timeLimitString != null && !timeLimitString.equals("") ){
+ try {
+ timeLimitSec = Integer.parseInt(timeLimitString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the limit as zero - which tells us not to use it.
+ }
+ }
+
+ if( timeLimitSec <= 0 ){
+ // We will NOT be using a timer
+ return queryByModel_Timed( transId, fromAppId, graph,
+ modelNameVersionId,
+ modelId,
+ modelName,
+ topNodeType,
+ startNodeFilterArrayOfHashes,
+ apiVer );
+ }
+
+ ArrayList <ResultSet> resultList = new ArrayList <ResultSet> ();
+ TimeLimiter limiter = new SimpleTimeLimiter();
+ try {
+ resultList = limiter.callWithTimeout(new Callable <ArrayList <ResultSet>>() {
+ public ArrayList <ResultSet> call() throws AAIException {
+ return queryByModel_Timed( transId_f, fromAppId_f, graph_f,
+ modelNameVersionId_f,
+ modelId_f,
+ modelName_f,
+ topNodeType_f,
+ startNodeFilterArrayOfHashes_f,
+ apiVer_f );
+ }
+ }, timeLimitSec, TimeUnit.SECONDS, true);
+ }
+ catch (AAIException ae) {
+ // Re-throw AAIException so we get can tell what happened internally
+ throw ae;
+ }
+ catch (UncheckedTimeoutException ute) {
+ throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
+ }
+ catch (Exception e) {
+ throw new AAIException("AAI_6128", "Unexpected exception in queryByModel(): " + e.getMessage() );
+ }
+
+
+ return resultList;
+ }
+
+
+ /**
+ * Query by model timed.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param modelId the model id
+ * @param modelName the model name
+ * @param topNodeType the top node type
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes
+ * @param apiVer the api ver
+ * @return the array list
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByModel_Timed( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId,
+ String modelId,
+ String modelName,
+ String topNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+
+
+ ArrayList <ResultSet> resultArray = new ArrayList <ResultSet> ();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "queryByModel");
+
+ // NOTE: this method can be used for different styles of queries:
+ // a) They could pass neither a modelNameVersionId or a modelId but just a set of data defining start-nodes.
+ // Note - with no model info, we need them to pass the startNodeType for us to be able to use the
+ // start-node-filter data. We would look at each start node and ensure that each has persona-model info.
+ // Use whatever model corresponds to each instance to pull that instance's data.
+ // b) They could pass a modelId, but no modelNameVersionId and no startNode info. In this case, we
+ // Would look in the database for all nodes that have a persona-model-id that matches what was
+ // passed, and then for each of those instances, pull the data based on the corresponding model.
+ // c) They could pass a model-name-version-id, but no startNode info. We'd make sure that if a
+ // model-id was also passed, that it does not conflict - but it really should be null if they
+ // are passing a full model-name-version-id. Like case -b-, we'd do a query for all nodes
+ // that have persona info that corresponds to the model-name-veersion-id passed and then
+ // collect data for each one.
+ // d) They could pass either modelNameVersionId or modelId AND startNodeFilter info. In this case we
+ // would look at the model info to figure out what the top-node-type is, then look at the
+ // top-node instances based on the startNodeFilter. We'd only collect data for each instance if
+ // it's persona model info matches what was passed in.
+
+
+ // ----------------------------------------------------------------------------------------------------------
+ // Get a Hash of all the start-nodes (top node for a model where we will start collecting data)
+ // for startNode2ModelHash: key = vertex-id for the startNode, value = modelNameVersionType for model
+ // ----------------------------------------------------------------------------------------------------------
+ HashMap <String, String> startNode2ModelHash = getStartNodesAndModels( transId, fromAppId, graph,
+ modelNameVersionId, modelId, modelName, topNodeType,
+ startNodeFilterArrayOfHashes, apiVer );
+
+ //System.out.println("\nDEBUG -- Here's a dump of the startnodes/models: " + startNode2ModelHash.toString());
+
+
+ // --------------------------------------------------------------------------------------------------------
+ // Figure out what-all models we're gonna be dealing with
+ // Note - Instances must all use the same type of start-node, but do not have to all use the same model.
+ // --------------------------------------------------------------------------------------------------------
+ HashMap <String, TitanVertex> distinctModelsHash = new HashMap <String,TitanVertex> ();
+ // For distinctModelsHash: key = modelTypeVersionId, val= modelVertex
+ String startNodeType = "";
+ if( topNodeType != null && !topNodeType.equals("") ){
+ startNodeType = topNodeType;
+ }
+
+ Set <String> snKeySet = startNode2ModelHash.keySet();
+ Iterator<String> startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ String modKey = startNode2ModelHash.get(vtxKey);
+ if( !distinctModelsHash.containsKey(modKey) ){
+ // First time seeing this model
+ TitanVertex modVtx = getModelUsingUUID(transId, fromAppId, graph, modKey);
+ String tmpNodeType = getModelWidgetType( modVtx, "" );
+ if( startNodeType.equals("") ){
+ startNodeType = tmpNodeType;
+ }
+ else if( !startNodeType.equals(tmpNodeType) ){
+ String msg = "Conflict between startNode types for models involved: [" + startNodeType
+ + "], [" + tmpNodeType + "]";
+ throw new AAIException("AAI_6125", msg);
+ }
+ distinctModelsHash.put(modKey, modVtx);
+ }
+ }
+
+ //System.out.println("\nDEBUG -- Here's a dump of the DISTINCT models hash: " + distinctModelsHash.toString() );
+
+ // ---------------------------------------------------------------------------------------------------------------
+ // Get the "valid-next-step" hash for each distinct model
+ // While we're at it, get a mapping of model-id|model-version to model-name-version-id for the models being used
+ // ---------------------------------------------------------------------------------------------------------------
+ HashMap <String, Multimap<String, String>> validNextStepHash = new HashMap <String, Multimap<String, String>>();
+ // validNextStepHash: key = modelNameVerId, value = nextStepMap
+ Set <String> keySet = distinctModelsHash.keySet();
+ Iterator<String> modelIterator = keySet.iterator();
+ while( modelIterator.hasNext() ){
+ String modKey = (String) modelIterator.next();
+ TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(modKey);
+ Multimap<String, String> tmpTopoMap = genTopoMap4Model( transId, fromAppId, graph,
+ modelVtx, modKey, dbMaps );
+ validNextStepHash.put(modKey, tmpTopoMap);
+ }
+
+ //System.out.println("\n\nDEBUG -- Here's a dump of the validNextStepHash "+ validNextStepHash.toString() );
+
+ // -------------------------------------------------------------------------------------------------
+ // Figure out what the "start-node" for each instance will be (plus the info we will use to
+ // represent that in our topology)
+ // -------------------------------------------------------------------------------------------------
+ ArrayList <String> failedPersonaCheckVids = new ArrayList <String> ();
+ HashMap <String, String> firstStepInfoHash = new HashMap <String,String> ();
+ // For firstStepInfoHash: key = startNodeVtxId, val=topNodeType plus personaData if applicable
+ // ie. the value is what we'd use as the "first-step" for this model.
+ if( !nodeTypeSupportsPersona( startNodeType, dbMaps) ){
+ // This node type doesn't have persona info, so we just use startNodeType for the first-step-info
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ firstStepInfoHash.put(vtxKey,startNodeType);
+ }
+ }
+ else {
+ // Need to check that this node's persona data is good and if it is - use it for the first step info
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ Iterator<Vertex> vtxIterator = graph.vertices(vtxKey);
+ TitanVertex tmpVtx = (TitanVertex)vtxIterator.next();
+ String thisVtxModelUUID = startNode2ModelHash.get(vtxKey);
+ TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(thisVtxModelUUID);
+ String modId = modelVtx.<String>property("model-id").orElse(null);
+ String modVersion = modelVtx.<String>property("model-version").orElse(null);
+ String personaModId = tmpVtx.<String>property("persona-model-id").orElse(null);
+ String personaModVersion = tmpVtx.<String>property("persona-model-version").orElse(null);
+
+ if( modId.equals(personaModId) && modVersion.equals(personaModVersion) ){
+ String tmpPersonaInfoStr = startNodeType + "," + personaModId + "," + personaModVersion;
+ firstStepInfoHash.put(vtxKey, tmpPersonaInfoStr );
+ }
+ else {
+ // we won't use this start node below when we collect data because it should have
+ // had persona data that matched it's model - but it did not.
+ failedPersonaCheckVids.add(vtxKey);
+ }
+ }
+ }
+
+ //System.out.println("\nDEBUG -- Here's a dump of the firstStepInfoHash hash: " + firstStepInfoHash.toString() );
+
+ // ------------------------------------------------------------------------------------------------
+ // Loop through each start-node, collect it's data using collectInstanceData() and put the
+ // resultSet onto the resultArray.
+ // ------------------------------------------------------------------------------------------------
+
+ // Make sure they're not bringing back too much data
+ String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
+ if( maxString != null && !maxString.equals("") ){
+ int maxSets = 0;
+ try {
+ maxSets = Integer.parseInt(maxString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the max as zero - which tells us not to use it.
+ }
+
+ if( maxSets > 0 && (startNode2ModelHash.size() > maxSets) ){
+ String msg = " Query returns " + startNode2ModelHash.size() + " resultSets. Max allowed is: " + maxSets;
+ throw new AAIException("AAI_6141", msg);
+ }
+ }
+
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String topNodeVtxId = (String) startNodeIterator.next();
+ if( failedPersonaCheckVids.contains(topNodeVtxId) ){
+ // Skip this vertex because it failed it's persona-data check above
+ continue;
+ }
+
+ Iterator<Vertex> vtxIterator = graph.vertices(topNodeVtxId);
+ TitanVertex tmpStartVtx = (TitanVertex)vtxIterator.next();
+ String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId);
+ String modelTypeNameVerId = startNode2ModelHash.get(topNodeVtxId);
+ Multimap<String, String> validNextStepMap = validNextStepHash.get(modelTypeNameVerId);
+
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyDelKeyHash = new HashMap <String,String> ();
+ HashMap <String,String> emptyNQElementHash = new HashMap <String,String> (); // Only applies to Named Queries
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ tmpStartVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, emptyNQElementHash, apiVer );
+
+ resultArray.add(tmpResSet);
+ }
+
+ return resultArray;
+
+ }// queryByModel()
+
+
+
+ /**
+ * Run delete by model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id -- unique id for a model
+ * @param topNodeTypeVal the top node type val -- required if no model-name-version-id is passed
+ * @param startNodeFilterHash the start node filter hash -- used to locate the first node of instance data
+ * @param apiVer the api ver
+ * @param resVersion the res version -- resourceVersion of the top/first widget in the model instance
+ * @return HashMap (keys = vertexIds that were deleted)
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> runDeleteByModel( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId, String topNodeTypeVal, HashMap <String,Object> startNodeFilterHash, String apiVer, String resVersion )
+ throws AAIException{
+
+ HashMap <String,String> retHash = new HashMap <String,String> ();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "runDeleteByModel");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to runDeleteByModel()\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));
+
+ // Locate the Model to be used
+ TitanVertex modelVtx = null;
+
+ if( modelNameVersionId != null && !modelNameVersionId.equals("") ){
+ HashMap <String,Object> propHash0 = new HashMap<String, Object>();
+ propHash0.put("model-name-version-id", modelNameVersionId);
+ modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash0, null, apiVer );
+ if( modelVtx == null ){
+ String msg = "No model found for model-name-version-id = [" + modelNameVersionId + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ else {
+ // if they didn't pass the modelNameVersionId, then we need to use the startNode to figure it out
+ // Locate the starting node based on the start node params
+ if( topNodeTypeVal == null || topNodeTypeVal.equals("") ){
+ String msg = "If no model info is passed, then topNodeType is required. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", msg);
+ }
+ TitanVertex startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNodeTypeVal, startNodeFilterHash, apiVer );
+ String startVertPersonaModId = startVtx.<String>property("persona-model-id").orElse(null);
+ String startVertPersonaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ modelVtx = getModelUsingPersonaInfo( transId, fromAppId, graph,
+ startVertPersonaModId, startVertPersonaModVersion );
+ }
+
+ if( modelVtx == null ){
+ String msg = "Could not determine the model for the given input parameters. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String topNType = "unknown";
+ String modelType = getModelType( modelVtx, "" );
+ if( modelType.equals("widget") ){
+ // If they want to delete using a widget-level model.. That is just a delete of the one
+ // instance of one of our nodes.
+ String widgModNodeType = modelVtx.<String>property("model-name").orElse(null);
+ if( (widgModNodeType == null) || widgModNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model [" + modelNameVersionId + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ TitanVertex widgetVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, widgModNodeType, startNodeFilterHash, null, apiVer );
+ String widgId = widgetVtx.id().toString();
+ DbMeth.removeAaiNode( transId, fromAppId, graph, widgetVtx, "USE_DEFAULT", "v7", resVersion);
+ retHash.put(widgId, widgModNodeType);
+ return( retHash );
+ }
+
+ // ----------------------------------------------------------------------------
+ // If we got to here, this must be either a service or resource model.
+ // So, we'll need to get a Hash of which parts of the model to delete.
+ // ----------------------------------------------------------------------------
+ String chkFirstNodePersonaModelId = "";
+ String chkFirstNodePersonaModelVersion = "";
+ String personaData = "";
+ TitanVertex firstModElementVertex = getTopElementForSvcOrResModel( modelVtx );
+ topNType = getElementWidgetType( firstModElementVertex, "" );
+ if( (topNType == null) || topNType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for model: [" + modelNameVersionId + "]";
+ throw new AAIException("AAI_6132", msg);
+ }
+ if( nodeTypeSupportsPersona(topNType, dbMaps) ){
+ chkFirstNodePersonaModelId = modelVtx.<String>property("model-id").orElse(null);
+ chkFirstNodePersonaModelVersion = modelVtx.<String>property("model-version").orElse(null);
+ personaData = "," + chkFirstNodePersonaModelId + "," + chkFirstNodePersonaModelVersion;
+ }
+
+ // Get the deleteKeyHash for this model
+ String incomingTrail = "";
+ HashMap <String, String> currentHash = new HashMap <String,String> ();
+ HashMap <String, TitanVertex> modConHash = new HashMap <String,TitanVertex> ();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String, String> delKeyHash = collectDeleteKeyHash( transId, fromAppId, graph,
+ firstModElementVertex, incomingTrail, currentHash, vidsTraversed,
+ 0, dbMaps, modConHash,
+ chkFirstNodePersonaModelId, chkFirstNodePersonaModelVersion );
+
+
+ //System.out.println("\n ----DEBUG -----: Delete Hash for model: [" + modelNameVersionId + "] looks like: ");
+ //for( Map.Entry<String, String> entry : delKeyHash.entrySet() ){
+ // System.out.println("key = [" + entry.getKey() + "], val = [" + entry.getValue() + "]");
+ //}
+ //System.out.println("\n -----");
+
+
+ // Locate the starting node that we'll use to start looking for instance data
+ TitanVertex startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterHash, apiVer );
+
+ if( !chkFirstNodePersonaModelId.equals("") ){
+ // NOTE: For Service or Resource models, if this is a nodeType that supports persona's, then
+ // we need to make sure that the start node matches the persona values.
+ String startVertPersonaModId = startVtx.<String>property("persona-model-id").orElse(null);
+ String startVertPersonaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ if( !chkFirstNodePersonaModelId.equals(startVertPersonaModId)
+ || !chkFirstNodePersonaModelVersion.equals(startVertPersonaModVersion) ){
+ String msg = "Persona-Model data mismatch for start node (" + topNType + "), " +
+ startNodeFilterHash ;
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ String topVid = startVtx.id().toString();
+
+ // Read the model into a Map for processing
+ Multimap <String, String> validNextStepMap = genTopoMap4Model(transId, fromAppId, graph,
+ modelVtx, modelNameVersionId, dbMaps );
+
+ logline.add("TopoMap", validNextStepMap.toString() );
+
+ // Collect the data
+ String elementLocationTrail = topNType + personaData;
+ vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyHash = new HashMap <String,String> ();
+
+ // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries
+ ResultSet retResSet = collectInstanceData( transId, fromAppId, graph,
+ startVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, delKeyHash, emptyHash, apiVer );
+
+ // Note: the new ResultSet will have each element tagged with the del flag so we'll know if it
+ // should be deleted or not - so loop through the results in a try-block since some things
+ // will get auto-deleted by parents before we get to them --- and try to remove each one.
+ String vidToResCheck = topVid;
+ retHash = deleteAsNeededFromResultSet( transId, fromAppId, graph, retResSet,
+ vidToResCheck, apiVer, resVersion, emptyHash );
+ String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + ").";
+
+ logline.add("DeleteReturnVal", msgStr);
+ return retHash;
+
+ }// End of runDeleteByModel()
+
+
+ /**
+ * Delete as needed from result set.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param resSet the res set
+ * @param vidToResCheck -- this vertex will need to have its resource-version checked
+ * @param apiVer the api ver
+ * @param resVersion the res version
+ * @param hashSoFar the hash so far -- hash of what's been deleted so far
+ * @return String
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> deleteAsNeededFromResultSet( String transId, String fromAppId, TitanTransaction graph,
+ ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, HashMap <String,String> hashSoFar )
+ throws AAIException
+ {
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deleteAsNeededFromResultSet");
+ HashMap <String,String> retHash = new HashMap <String,String> ();
+ retHash.putAll( hashSoFar );
+ Boolean deleteIt = false;
+
+ if( graph == null ){
+ String emsg = "null graph object passed to deleteAsNeededFromResultSet()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( resSet.vert == null ){
+ return retHash;
+ }
+
+ TitanVertex thisVtx = resSet.vert;
+ String thisGuyId = "";
+ String thisNT = "";
+ String thisGuyStr = "";
+
+ try {
+ thisGuyId = thisVtx.id().toString();
+ thisNT = thisVtx.<String>property("aai-node-type").orElse(null);
+ thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + resSet.locationInModelSubGraph + "]";
+ }
+ catch (Exception ex) {
+ // Sometimes things have already been deleted by the time we get to them - just log it.
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + ". msg = " + ex.getMessage();
+ logline.add("warnMsg", warnMsg);
+ }
+
+ if( thisGuyId.equals("") ){
+ // The vertex must have already been removed. Just return.
+ return retHash;
+ }
+ else {
+ if( resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T") ){
+ String infoMsg = ">> will try to delete this one >> " + thisGuyStr ;
+ logline.add("infoMsg", infoMsg);
+
+ try {
+ Boolean resVerOverRide = true;
+ if( thisGuyId.equals(vidToResCheck) ){
+ // This is the one vertex that we want to check the resourceId before deleting
+ resVerOverRide = false;
+ }
+ DbMeth.removeAaiNode( transId, fromAppId, graph, thisVtx, "USE_DEFAULT", apiVer, resVersion, resVerOverRide );
+ }
+ catch (AAIException ae) {
+ String errorCode = ae.getErrorObject().getErrorCode();
+ if ( errorCode.equals("6130") || errorCode.equals("6131") ) {
+ // They didn't pass the correct resource-version for the top node.
+ throw ae;
+ }
+ else {
+ String errText = ae.getErrorObject().getErrorText();
+ String errDetail = ae.getErrorObject().getDetails();
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + ". ErrorCode = " + errorCode +
+ ", errorText = " + errText + ", details = " + errDetail;
+ logline.add("warnMsg", warnMsg);
+ }
+ }
+ catch( Exception e ){
+ // We'd expect to get a "node not found" here sometimes depending on the order that
+ // the model has us finding / deleting nodes.
+ // Ignore the exception - but log it so we can see what happened.
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + e.getMessage();
+ //System.out.println(" \nDEBUG --- " + warnMsg );
+ logline.add("warnMsg", warnMsg);
+ }
+
+ // We can't depend on a thrown exception to tell us if a node was deleted since it may
+ // have been auto=deleted before this removeAaiNode() call.
+ // --- Not sure if we would want to check anything here -- because the graph.commit() is done outside of this call.
+
+ deleteIt = true;
+ }
+ else {
+ // --- DEBUG ----
+ //System.out.println(">>>>>>> NOT DELETING THIS ONE >>>> " + thisGuyStr );
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode(transId, fromAppId, thisVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+ // --- DEBUG ----
+ }
+ }
+
+ // Now call this routine for the sub-resultSets
+ List <ResultSet> subResultSetList = resSet.getSubResultSet();
+ Iterator <ResultSet> subResSetIter = subResultSetList.iterator();
+ while( subResSetIter.hasNext() ){
+ ResultSet tmpSubResSet = subResSetIter.next();
+ retHash = deleteAsNeededFromResultSet( transId, fromAppId, graph, tmpSubResSet,
+ vidToResCheck, apiVer, resVersion, retHash );
+ }
+
+ if( deleteIt ){
+ retHash.put(thisGuyId, thisGuyStr);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return retHash;
+
+ }// deleteAsNeededFromResultSet()
+
+
+ /**
+ * Query by named query.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByNamedQuery( String transId, String fromAppId, TitanTransaction graph,
+ String namedQueryUuid,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ final String transId_f = transId;
+ final String fromAppId_f = fromAppId;
+ final TitanTransaction graph_f = graph;
+ final String namedQueryUuid_f = namedQueryUuid;
+ final ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
+ final String apiVer_f = apiVer;
+
+ // Find out what our time-limit should be
+ int timeLimitSec = 0;
+ String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
+ if( timeLimitString != null && !timeLimitString.equals("") ){
+ try {
+ timeLimitSec = Integer.parseInt(timeLimitString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the limit as zero - which tells us not to use it.
+ }
+ }
+
+ if( timeLimitSec <= 0 ){
+ // We will NOT be using a timer
+ return queryByNamedQuery_Timed( transId, fromAppId, graph,
+ namedQueryUuid,
+ startNodeFilterArrayOfHashes,
+ apiVer );
+ }
+
+ ArrayList <ResultSet> resultList = new ArrayList <ResultSet> ();
+ TimeLimiter limiter = new SimpleTimeLimiter();
+ try {
+ resultList = limiter.callWithTimeout(new Callable <ArrayList <ResultSet>>() {
+ public ArrayList <ResultSet> call() throws AAIException {
+ return queryByNamedQuery_Timed( transId_f, fromAppId_f, graph_f,
+ namedQueryUuid_f,
+ startNodeFilterArrayOfHashes_f,
+ apiVer_f );
+ }
+ }, timeLimitSec, TimeUnit.SECONDS, true);
+
+ }
+ catch (AAIException ae) {
+ // Re-throw AAIException so we get can tell what happened internally
+ throw ae;
+ }
+ catch (UncheckedTimeoutException ute) {
+ throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
+ }
+ catch (Exception e) {
+ throw new AAIException("AAI_6128", "Unexpected exception in queryByNamedQuery(): " + e.getMessage() );
+ }
+
+ return resultList;
+ }
+
+
+ /**
+ * Query by named query timed.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByNamedQuery_Timed( String transId, String fromAppId, TitanTransaction graph,
+ String namedQueryUuid,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "queryByNamedQuery");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to queryByNamedQuery()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ // Locate the Query to be used
+ HashMap <String,Object> propHash0 = new HashMap<String, Object>();
+ propHash0.put("named-query-uuid", namedQueryUuid);
+ TitanVertex queryVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "named-query", propHash0, null, apiVer );
+ if( queryVtx == null ){
+ String msg = "No named-query found for named-query-uuid = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+
+ //System.out.println("\n DEBUG --- Found query vertex: " );
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode("junkId", "junkApp", queryVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+
+
+ // Get the first/top named-query-element used by this query
+ Iterable <?> verts = queryVtx.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ TitanVertex firstNqElementVert = null;
+ int count = 0;
+ String topNType = "";
+ while( vertI != null && vertI.hasNext() ){
+ firstNqElementVert = (TitanVertex) vertI.next();
+ count++;
+ topNType = getElementWidgetType( firstNqElementVert, "" );
+ }
+
+ if( count < 1 ){
+ // A named query must start with a single top element
+ String msg = "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+ else if( count > 1 ){
+ // A named query should start with a single top element
+ String msg = "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+ if( (topNType == null) || topNType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for Named Query: [" + namedQueryUuid + "]";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ // Read the topology into a hash for processing
+ Multimap <String, String> validNextStepMap = genTopoMap4NamedQ(transId, fromAppId, graph, queryVtx, namedQueryUuid);
+
+ ArrayList <TitanVertex> startVertList = new ArrayList <TitanVertex>();
+ if( startNodeFilterArrayOfHashes.size() == 1 ){
+ // If there is only one set of startFilter info given, then allow it to possibly not be
+ // defining just one start node.
+ try {
+ TitanVertex tmpVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterArrayOfHashes.get(0), apiVer );
+ // Only found one, so just use it.
+ startVertList.add(tmpVtx);
+ }
+ catch( AAIException ate ){
+ // Either there is more than one node found using these parameters or these
+ // were not the key params. Either way, see if they can lead us to some start-nodes.
+
+ // NOTE: for now, getNodes() is only taking parameters for the nodeType passed, so if
+ // any of the parameters have the nodeType appended, it should be stripped off.
+ // Ie. "customer.global-cust-id" should be passed just as, "global-cust-id"
+ HashMap <String, Object> cleanHash = new HashMap <String,Object>();
+ HashMap <String, Object> tmpHash = startNodeFilterArrayOfHashes.get(0);
+ Set <String> propKeySet = tmpHash.keySet();
+ Iterator<String> propIter = propKeySet.iterator();
+ while( propIter.hasNext() ){
+ String oldVtxKey = (String) propIter.next();
+ String newKey = oldVtxKey;
+ String [] parts = oldVtxKey.split("\\.");
+ if( parts.length == 2 ){
+ newKey = parts[1];
+ }
+ Object obVal = tmpHash.get(oldVtxKey);
+ cleanHash.put(newKey,obVal);
+ }
+
+ startVertList = DbMeth.getNodes( transId, fromAppId, graph, topNType,
+ cleanHash, false, apiVer, true );
+
+ if( startVertList.isEmpty() ){
+ String msg = "No Node of type [" + topNType + "] found for properties: " + cleanHash.toString();
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ }
+ else {
+ // Since they give an array of startNodeFilterHash info, we expect each one
+ // to just point to one node.
+ for( int i = 0; i < startNodeFilterArrayOfHashes.size(); i++ ){
+ // Locate the starting node for each set of data
+ TitanVertex tmpVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterArrayOfHashes.get(i), apiVer );
+ startVertList.add(tmpVtx);
+ }
+ }
+
+ // Make sure they're not bringing back too much data
+ String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
+ if( maxString != null && !maxString.equals("") ){
+ int maxSets = Integer.parseInt(maxString);
+ if( startVertList.size() > maxSets ){
+ String msg = " Query returns " + startVertList.size() + " resultSets. Max allowed is: " + maxSets;
+ throw new AAIException("AAI_6141", msg);
+ }
+ }
+
+ // Loop through each start node and get its data
+ ArrayList <ResultSet> resSetList = new ArrayList <ResultSet> ();
+ for( int i = 0; i < startVertList.size(); i++ ){
+ TitanVertex startVtx = startVertList.get(i);
+ // Collect the data
+ String elementLocationTrail = topNType;
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyDelKeyHash = new HashMap <String,String> (); // Does not apply to Named Queries
+
+ // Get the mapping of namedQuery elements to our widget topology for this namedQuery
+ String incomingTrail = "";
+ HashMap <String, String> currentHash = new HashMap <String,String> ();
+
+ HashMap <String,String> namedQueryElementHash = collectNQElementHash( transId, fromAppId, graph,
+ firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 );
+
+ vidsTraversed = new ArrayList <String> ();
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ startVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, namedQueryElementHash, apiVer );
+ resSetList.add(tmpResSet);
+ }
+
+ // Since a NamedQuery can mark some nodes as "do-not-display", we need to collapse our resultSet so
+ // does not display those nodes.
+ ArrayList <ResultSet> collapsedResSetList = new ArrayList <ResultSet> ();
+ if( resSetList != null && !resSetList.isEmpty() ){
+ for( int i = 0; i < resSetList.size(); i++ ){
+ // Note - a single resultSet could be collapsed into many smaller ones if they
+ // marked all the "top" node-elements as do-not-output. Ie. the query may
+ // have had a top-node of "generic-vnf" which joins down to different l-interfaces.
+ // If they only want to see the l-interfaces, then a single result set
+ // would be "collapsed" into many separate resultSets - each of which is
+ // just a single l-interface.
+ ArrayList <ResultSet> tmpResSetList = collapseForDoNotOutput(resSetList.get(i));
+ if( tmpResSetList != null && !tmpResSetList.isEmpty() ){
+ for( int x = 0; x < tmpResSetList.size(); x++ ){
+ collapsedResSetList.add(tmpResSetList.get(x));
+ }
+ }
+ }
+ }
+
+ return collapsedResSetList;
+
+
+ }// End of queryByNamedQuery()
+
+
+ /**
+ * Collapse for do not output.
+ *
+ * @param resSetVal the res set val
+ * @return the array list
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> collapseForDoNotOutput( ResultSet resSetVal )
+ throws AAIException {
+
+ // Given a ResultSet -- if it is tagged to NOT be output, then replace it with
+ // it's sub-ResultSets if it has any.
+ ArrayList <ResultSet> colResultSet = new ArrayList <ResultSet> ();
+
+ if( resSetVal.getDoNotOutputFlag().equals("true") ){
+ // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets
+ ArrayList <ResultSet> subResList = (ArrayList<ResultSet>) resSetVal.getSubResultSet();
+ for( int k = 0; k < subResList.size(); k++ ){
+ ArrayList <ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(k));
+ colResultSet.addAll(newSubResList);
+ }
+ }
+ else {
+ // This set will be displayed
+ colResultSet.add(resSetVal);
+ }
+
+ // For each result set now at this level, call this same routine to collapse their sub-resultSets
+ for( int i = 0; i < colResultSet.size(); i++ ){
+ ArrayList <ResultSet> newSubSet = new ArrayList <ResultSet> ();
+ ArrayList <ResultSet> subResList = (ArrayList<ResultSet>) colResultSet.get(i).getSubResultSet();
+ for( int n = 0; n < subResList.size(); n++ ){
+ ArrayList <ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(n));
+ newSubSet.addAll(newSubResList);
+ }
+ // Replace the old subResultSet with the collapsed set
+ colResultSet.get(i).subResultSet = newSubSet;
+ }
+
+ return colResultSet;
+
+ }// End collapseForDoNotOutput()
+
+
+
+ /**
+ * Collect instance data.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param thisVertsTrail the this verts trail
+ * @param elementLocationTrail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param validNextStepMap the valid next step map -- hash of valid next steps (node types) for this model
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param delKeyHash -- hashMap of which spots on our topology should be deleted during a modelDelete
+ * @param namedQueryElementHash - hashMap which maps each spot in our widget topology to the NamedQueryElemment that it maps to
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ResultSet collectInstanceData( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex,
+ String thisVertsTrail,
+ Multimap <String,String> validNextStepMap,
+ ArrayList <String> vidsTraversed,
+ int levelCounter,
+ HashMap <String,String> delKeyHash, // only applies when collecting data using the default model for delete
+ HashMap <String,String> namedQueryElementHash, // only applies to named-query data collecting
+ String apiVer
+ ) throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectInstanceData");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to collectInstanceData()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ String thisVid = thisLevelVertex.id().toString();
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectInstanceData() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ ResultSet rs = new ResultSet();
+ if( namedQueryElementHash.containsKey(thisVertsTrail) ){
+ // We're collecting data for a named-query, so need to see if we need to do anything special
+ String nqElUuid = namedQueryElementHash.get(thisVertsTrail);
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "named-query-element-uuid", nqElUuid );
+ TitanVertex nqElementVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "named-query-element", propHash, null, apiVer);
+ if( nqElementVtx == null ){
+ String msg = " Could not find named-query-element with named-query-element-uuid = [" + nqElUuid + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String tmpDoNotShow = nqElementVtx.<String>property("do-not-output").orElse(null);
+ if( tmpDoNotShow != null && tmpDoNotShow.equals("true") ){
+ rs.doNotOutputFlag = "true";
+ }
+
+ if( namedQueryConstraintSaysStop(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer) ){
+ // There was a property constraint which says they do not want to collect this vertex or whatever
+ // might be below it. Just return the empty rs here.
+ return rs;
+ }
+
+ String propLimDesc = nqElementVtx.<String>property("property-limit-desc").orElse(null);
+ if( (propLimDesc != null) && !propLimDesc.equals("") ){
+ rs.propertyLimitDesc = propLimDesc;
+ }
+
+ // Look to see if we need to use an Override of the normal properties
+ HashMap <String,Object> tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer);
+ //System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + tmpPropertyOverRideHash.toString() + "]");
+ rs.propertyOverRideHash = tmpPropertyOverRideHash;
+
+ // See if we need to look up any "unconnected" data that needs to be associated with this result set
+ HashMap <String,Object> tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer);
+ //System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + tmpExtraPropHash.toString() + "]");
+ rs.extraPropertyHash = tmpExtraPropHash;
+ }
+
+ rs.vert = thisLevelVertex;
+ rs.locationInModelSubGraph = thisVertsTrail;
+ if( delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T") ){
+ rs.newDataDelFlag = "T";
+ }
+ else {
+ rs.newDataDelFlag = "F";
+ }
+
+ // Use Gremlin-pipeline to just look for edges that go to a valid "next-steps"
+ Collection <String> validNextStepColl = validNextStepMap.get(thisVertsTrail);
+
+ // Because of how we process linkage-points, we may have duplicate node-types in our next-stepMap (for one step)
+ // So, to keep from looking (and bringing back) the same data twice, we need to make sure our next-steps are unique
+ HashSet <String> validNextStepHashSet = new HashSet <String> ();
+ Iterator <String> ntcItr = validNextStepColl.iterator();
+ while( ntcItr.hasNext() ){
+ String targetStepStr = ntcItr.next();
+ validNextStepHashSet.add(targetStepStr);
+ }
+
+ ArrayList <String> tmpVidsTraversedList = new ArrayList <String> ();
+ tmpVidsTraversedList.addAll(vidsTraversed);
+ tmpVidsTraversedList.add(thisVid);
+
+ Iterator <String> ntItr = validNextStepHashSet.iterator();
+ while( ntItr.hasNext() ){
+ String targetStep = ntItr.next();
+ // NOTE: NextSteps can either be just a nodeType, or can be a nodeType plus
+ // persona-model-id and persona-model-version if those need to be checked also.
+ // When the persona stuff is part of the step, it is a comma separated string.
+ // Ie. "nodeType,personaModelId,personaModeVersion"
+ String targetNodeType = "";
+ String pmid = "";
+ String pmv = "";
+ Boolean stepIsJustNT = true;
+ if( targetStep.contains(",") ){
+ stepIsJustNT = false;
+ String[] pieces = targetStep.split(",");
+ if( pieces.length != 3 ){
+ String msg = "Unexpected format for nextStep in model processing = ["
+ + targetStep + "]. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6128");
+ throw new AAIException("AAI_6128", msg);
+ }
+ else {
+ targetNodeType = pieces[0];
+ pmid = pieces[1];
+ pmv = pieces[2];
+ }
+ }
+ else {
+ // It's just the nodeType with no other info
+ targetNodeType = targetStep;
+ }
+
+ GraphTraversal<Vertex, Vertex> modPipe = null;
+ if( stepIsJustNT ){
+ modPipe = graph.traversal().V(thisLevelVertex).both().has("aai-node-type", targetNodeType);
+ }
+ else {
+ modPipe = graph.traversal().V(thisLevelVertex).both().has("aai-node-type", targetNodeType).has("persona-model-id",pmid).has("persona-model-version",pmv);
+ }
+
+ if( modPipe == null || !modPipe.hasNext() ){
+ //System.out.println("DEBUG - didn't find any [" + targetStep + "] connected to this guy (which is ok)");
+ }
+ else {
+ while( modPipe.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) modPipe.next();
+ String tmpVid = tmpVert.id().toString();
+ String tmpTrail = thisVertsTrail + "|" + targetStep;
+ if( !vidsTraversed.contains(tmpVid) ){
+ // This is one we would like to use - so we'll include the result set we get for it
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ tmpVert, tmpTrail,
+ validNextStepMap, tmpVidsTraversedList,
+ levelCounter, delKeyHash, namedQueryElementHash, apiVer );
+
+ rs.subResultSet.add(tmpResSet);
+ }
+ }
+ }
+ }
+
+ return rs;
+
+ } // End of collectInstanceData()
+
+
+ /**
+ * Gen topo map 4 model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelVertex the model vertex
+ * @param modelUuid the model uuid
+ * @param dbMaps the db maps
+ * @return MultiMap of valid next steps for each potential model-element
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> genTopoMap4Model( String transId, String fromAppId,
+ TitanTransaction graph, TitanVertex modelVertex, String modelUuid, DbMaps dbMaps )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "genTopoMap4Model");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to genTopoMap4Model()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( modelVertex == null ){
+ String msg = " null modelVertex passed to genTopoMap4Model() ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ Multimap <String, String> initialEmptyMap = ArrayListMultimap.create();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+
+ String modelType = getModelType( modelVertex, "" );
+ if( modelType.equals("widget") ){
+ // A widget model by itself does not have a topoplogy. That is - it has no "model-elements" which
+ // define how it is connected to other things. All it has is a name which ties it to
+ // an aai-node-type
+ Iterable <?> verts = modelVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ if( vertI != null && vertI.hasNext() ){
+ String msg = "Bad Model Definition: Widget Model with a startsWith edge to a model-element. "
+ + " Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+ else {
+ return initialEmptyMap;
+ }
+ }
+
+ String firstModelId = modelVertex.<String>property("model-id").orElse(null);
+ String firstModelVersion = modelVertex.<String>property("model-version").orElse(null);
+ if( firstModelId == null || firstModelId.equals("") || firstModelVersion == null || firstModelVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = "
+ + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ TitanVertex firstElementVertex = getTopElementForSvcOrResModel( modelVertex );
+ TitanVertex firstEleModVtx = getModelThatElementRepresents( firstElementVertex, "" );
+ String firstElemModelType = getModelType( firstEleModVtx, "" );
+ if( ! firstElemModelType.equals("widget") ){
+ String msg = "Bad Model Definition: First element must correspond to a widget type model. Model UUID = "
+ + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ Multimap <String, String> collectedMap = collectTopology4Model( transId, fromAppId, graph,
+ firstElementVertex, "",
+ initialEmptyMap, vidsTraversed, 0, dbMaps, null, firstModelId, firstModelVersion );
+
+ //DEBUG -----------------
+ //System.out.println("DEBUG -- go this topo map for this model: ");
+ //Set keySet = collectedMap.keySet();
+ //Iterator keyIterator = keySet.iterator();
+ //while (keyIterator.hasNext() ) {
+ // String key = (String) keyIterator.next();
+ // System.out.println( "DEBUG -- for this key: [" + key + "], got these values: ");
+ // Collection <String> values = collectedMap.get(key) ;
+ // Iterator valIter = values.iterator();
+ // while( valIter.hasNext() ){
+ // System.out.println(" >>> [" + valIter.next() + "]");
+ // }
+ //}
+ //DEBUG -------------------------
+
+ return collectedMap;
+
+ } // End of genTopoMap4Model()
+
+
+
+ /**
+ * Gets the mod constraint hash.
+ *
+ * @param modelElementVtx the model element vtx
+ * @param currentHash -- the current ModelConstraint's that this routine will add to if it finds any.
+ * @return HashMap of model-constraints that will be looked at for this model-element and what's "below" it.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, TitanVertex> getModConstraintHash( TitanVertex modelElementVtx, HashMap <String, TitanVertex> currentHash )
+ throws AAIException {
+
+ // For a given model-element vertex, look to see if there are any "model-constraint" elements that is has
+ // an OUT "uses" edge to. If it does, then get any "constrained-element-set" nodes that are pointed to
+ // by the "model-constraint". That will be the replacement "constrained-element-set". The UUID of the
+ // "constrained-element-set" that it is supposed to replace is found in the property:
+ // model-constraint.constrained-element-set-uuid-to-replace
+ //
+ // For now, that is the only type of model-constraint allowed, so that is all we will look for.
+ // Pass back any of these "constrained-element-set" nodes along with any that were passed in by
+ // the "currentHash" parameter.
+
+ if( modelElementVtx == null ){
+ String msg = " null modelElementVtx passed to getModConstraintHash() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelElementVtx.<String>property("aai-node-type").orElse(null);
+ if( modelType == null || (!modelType.equals("model-element")) ){
+ String msg = " getModConstraintHash() called with wrong type model: [" + modelType + "]. ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ HashMap <String, TitanVertex> thisHash = new HashMap <String, TitanVertex> ();
+ if( currentHash != null ){
+ thisHash.putAll(currentHash);
+ }
+
+ int count = 0;
+ ArrayList <TitanVertex> modelConstraintArray = new ArrayList <TitanVertex> ();
+ Iterable <?> verts = modelElementVtx.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> vertI = verts.iterator();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( (connectToType != null) && connectToType.equals("model-constraint") ){
+ // We need to find the constrained element set pointed to by this and add it to the Hash to return
+ modelConstraintArray.add(tmpVert);
+ count++;
+ }
+ }
+
+ if( count > 0 ) {
+ for( int i = 0; i < count; i++ ){
+ TitanVertex vtxOfModelConstraint = modelConstraintArray.get(i);
+ String uuidOfTheOneToBeReplaced = vtxOfModelConstraint.<String>property("constrained-element-set-uuid-2-replace").orElse(null);
+ // We have the UUID of the constrained-element-set that will be superseded, now find the
+ // constrained-element-set to use in its place
+ Iterable <?> mverts = vtxOfModelConstraint.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> mvertI = mverts.iterator();
+ while( mvertI != null && mvertI.hasNext() ){
+ // There better only be one...
+ TitanVertex tmpVert = (TitanVertex) mvertI.next();
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // This is the "constrained-element-set" that we want to use as the Replacement
+ thisHash.put(uuidOfTheOneToBeReplaced, tmpVert );
+ }
+ }
+ }
+ return thisHash;
+ }
+ else {
+ // Didn't find anything to add, so just return what they passed in.
+ return currentHash;
+ }
+
+ } // End of getModConstraintHash()
+
+
+ /**
+ * Gets the top element for svc or res model.
+ *
+ * @param modelVertex the model vertex
+ * @return first element pointed to by this model
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getTopElementForSvcOrResModel( TitanVertex modelVertex )
+ throws AAIException {
+
+ // For a "resource" or "service" type model, return the "top" element in that model
+ if( modelVertex == null ){
+ String msg = " null modelVertex passed to getTopoElementForSvcOrResModel() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelVertex.<String>property("model-type").orElse(null);
+ if( modelType == null || (!modelType.equals("service")) && (!modelType.equals("resource")) ){
+ String msg = " getTopElementForSvcOrResModel() called with wrong type model: [" + modelType + "]. ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ String modelUuid = modelVertex.<String>property("model-name-version-id").orElse(null);
+
+ TitanVertex firstElementVertex = null;
+ Iterable <?> verts = modelVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+
+ Iterator <?> vertI = verts.iterator();
+ int elCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ elCount++;
+ firstElementVertex = (TitanVertex) vertI.next();
+ }
+
+ if( elCount > 1 ){
+ String msg = "Illegal model defined: More than one first element defined for = " + modelUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ if( firstElementVertex == null ){
+ String msg = "Could not find first model element = " + modelUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return firstElementVertex;
+
+ } // End of getTopElementForSvcOrResModel()
+
+
+
+ /**
+ * Gets the named query prop over ride.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return HashMap of alternate properties to return for this element
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNamedQueryPropOverRide( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // If this model-element says that they want an alternative set of properties returned, then pull that
+ // data out of the instance vertex.
+
+ HashMap <String,Object> altPropHash = new HashMap <String,Object> ();
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ ArrayList <String> propCollectList = new ArrayList <String> ();
+ Iterator <VertexProperty<Object>> vpI = namedQueryElementVertex.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ VertexProperty <Object> vpOb = vpI.next();
+ // Some property-collect-lists are winding up in the database as toString() versions of
+ // an arrayList instead of as ArrayLists or as multiple properties with the same name.
+ // Whichever it is, we need to handle it.
+ ArrayList <String> propCollList = makeSureItsAnArrayList( vpOb );
+ if( propCollList != null ){
+ for( int i = 0; i < propCollList.size(); i++ ){
+ String thisPropName = propCollList.get(i);
+ Object instanceVal = instanceVertex.<Object>property(thisPropName).orElse(null);
+ altPropHash.put(thisPropName, instanceVal);
+ }
+ }
+ }
+
+ return altPropHash;
+
+ } // End of getNamedQueryPropOverRide()
+
+
+ /**
+ * Named query constraint says stop.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return true - if a constraint was defined that has not been met by the passed instanceVertex
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean namedQueryConstraintSaysStop( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // For each (if any) property-constraint defined for this named-query-element, we will evaluate if
+ // the constraint is met or not-met. if there are constraints and any are not-met, then
+ // we return "true".
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to namedQueryConstraintSaysStop() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ if( instanceVertex == null ){
+ String msg = " null instanceVertex passed to namedQueryConstraintSaysStop() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ GraphTraversal<Vertex, Vertex> constrPipe = graph.traversal()
+ .V(namedQueryElementVertex).out("uses").has("aai-node-type","property-constraint");
+
+ if( constrPipe == null || !constrPipe.hasNext() ){
+ // There's no "property-constraint" defined for this named-query-element. No problem.
+ return false;
+ }
+
+ while( constrPipe.hasNext() ){
+ TitanVertex constrVtx = (TitanVertex) constrPipe.next();
+ // We found a property constraint that we will need to check
+ String conType = constrVtx.<String>property("constraint-type").orElse(null);
+ if( (conType == null) || conType.equals("")){
+ String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String propName = constrVtx.<String>property("property-name").orElse(null);
+ if( (propName == null) || propName.equals("")){
+ String msg = " Bad property-constraint (property-name) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String propVal = constrVtx.<String>property("property-value").orElse(null);
+ if( (propVal == null) || propVal.equals("")){
+ String msg = " Bad property-constraint (propVal) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ // See if that constraint is met or not
+ String val = instanceVertex.<String>property(propName).orElse(null);
+ if( val == null ){
+ val = "";
+ }
+
+ if( conType.equals("EQUALS") ){
+ if( !val.equals(propVal) ){
+ // This constraint was not met
+ return true;
+ }
+ }
+ else if( conType.equals("NOT-EQUALS") ){
+ if( val.equals(propVal) ){
+ // This constraint was not met
+ return true;
+ }
+ }
+ else {
+ String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ }
+
+ return false;
+
+ } // End of namedQueryConstraintSaysStop()
+
+
+ /**
+ * Gets the named query extra data lookup.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return HashMap of alternate properties to return for this element
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNamedQueryExtraDataLookup( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // For each (if any) related-lookup defined for this named-query-element, we will go and
+ // and try to find it. All the related-lookup data will get put in a hash and returned.
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to getNamedQueryExtraDataLookup() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ if( instanceVertex == null ){
+ String msg = " null instanceVertex passed to getNamedQueryExtraDataLookup() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ HashMap <String,Object> retHash = new HashMap <String,Object> ();
+
+ GraphTraversal<Vertex, Vertex> lookPipe = graph.traversal()
+ .V(namedQueryElementVertex).out("uses").has("aai-node-type","related-lookup");
+
+ if( lookPipe == null || !lookPipe.hasNext() ){
+ // There's no "related-lookup" defined for this named-query-element. No problem.
+ return retHash;
+ }
+
+ while( lookPipe.hasNext() ){
+ TitanVertex relLookupVtx = (TitanVertex) lookPipe.next();
+
+ //System.out.println("DEBUG --- found a related-lookup record -- ");
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode("junkId", "junkApp", relLookupVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+
+ // We found a related-lookup record to try and use
+ String srcProp = relLookupVtx.<String>property("source-node-property").orElse(null);
+ if( (srcProp == null) || srcProp.equals("")){
+ String msg = " Bad related-lookup (source-node-property) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String targetNodeType = relLookupVtx.<String>property("target-node-type").orElse(null);
+ if( (targetNodeType == null) || targetNodeType.equals("")){
+ String msg = " Bad related-lookup (targetNodeType) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String targetProp = relLookupVtx.<String>property("target-node-property").orElse(null);
+ if( (targetProp == null) || targetProp.equals("")){
+ String msg = " Bad related-lookup (target-node-property) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ /***
+ ArrayList <String> propCollectList = new ArrayList <String>();
+ Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ VertexProperty <Object> vpOb = vpI.next();
+ // Some property-collect-lists are winding up in the database as toString() versions of
+ // an arrayList instead of as ArrayLists or as multiple properties with the same name.
+ // Whichever it is, we need to handle it.
+ ArrayList <String> propCList = makeSureItsAnArrayList( vpOb );
+ if( propCList != null ){
+ for( int i = 0; i < propCList.size(); i++ ){
+ String thisPropName = propCList.get(i);
+ propCollectList.add(thisPropName);
+ }
+ }
+ }
+ ***/
+
+ ArrayList <String> propCollectList = new ArrayList <String> ();
+ Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ propCollectList.add((String)vpI.next().value());
+ }
+
+
+
+
+ // Use the value from the source to see if we can find ONE target record using the value from the source
+ String valFromInstance = instanceVertex.<String>property(srcProp).orElse(null);
+ if( valFromInstance == null ){
+ valFromInstance = "";
+ }
+
+ HashMap <String,Object> propHash = new HashMap <String,Object>();
+ propHash.put(targetProp, valFromInstance);
+ ArrayList <TitanVertex> vertList = DbMeth.getNodes(transId, fromAppId, graph, targetNodeType, propHash, true, apiVer, true);
+ int foundCount = vertList.size();
+
+ if( foundCount == 0 ){
+ //System.out.println("\n\n---------- FOUND NOTHING on the related lookup for: [" + targetNodeType
+ // + "], using propHash = [" + propHash + "]\n");
+ }
+ else if( foundCount > 1 ){
+ //System.out.println("DEBUG -- can't use this because there are too many records found using targetNodeType = ["
+ // + targetNodeType + "], with property Hash = [" + propHash + "]\n");
+ }
+ else {
+ TitanVertex tmpVtx = vertList.get(0);
+ //System.out.println("\nDEBUG -- Found a related vertex using our lookup ");
+ // Pick up the properties from the target vertex that they wanted us to get
+ for( int j = 0; j < propCollectList.size(); j++ ){
+ String tmpPropName = propCollectList.get(j);
+ Object valObj = tmpVtx.<Object>property(tmpPropName).orElse(null);
+ String lookupKey = targetNodeType + "." + tmpPropName;
+ retHash.put(lookupKey, valObj);
+ }
+ }
+ }
+
+ return retHash;
+
+ } // End of getNamedQueryExtraDataLookup()
+
+
+ /**
+ * Collect NQ element hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this nq-element vertex) from the top
+ * @param currentHash the current hash
+ * @param Map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @return HashMap of all widget-points on a namedQuery topology with the value being the "named-query-element-uuid" for that spot.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, String> collectNQElementHash( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ HashMap <String,String> currentHash, ArrayList <String> vidsTraversed,
+ int levelCounter ) throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectNQElementHash");
+
+ HashMap <String, String> thisHash = new HashMap <String,String> ();
+ thisHash.putAll(currentHash);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectNQElementHash() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
+ }
+ vidsTraversed.add(thisVid);
+
+ String nqElementUuid = thisLevelVertex.<String>property("named-query-element-uuid").orElse(null);
+ if( nqElementUuid == null || nqElementUuid.equals("") ){
+ String msg = " named-query element UUID not found at trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6133", msg);
+ }
+ thisHash.put(thisGuysTrail, nqElementUuid );
+
+ // Now go "down" and look at the sub-elements pointed to so we can get their data.
+ Iterable <?> verts = thisLevelVertex.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("named-query-element") ){
+ // This is what we would expect
+ elementHash.put(vid, tmpVert);
+ }
+ else {
+ String msg = " named query element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6133", msg);
+ }
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ HashMap <String, String> tmpHash = collectNQElementHash( transId, fromAppId, graph,
+ elVert, thisGuysTrail, currentHash, vidsTraversed, levelCounter);
+ thisHash.putAll(tmpHash);
+ }
+ }
+ }
+ return thisHash;
+
+ } // End of collectNQElementHash()
+
+
+ /**
+ * Collect delete key hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param currentHash the current hash
+ * @param Map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed ---- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param dbMaps the db maps
+ * @param modConstraintHash the mod constraint hash
+ * @param overRideModelId the over ride model id
+ * @param overRideModelVersion the over ride model version
+ * @return HashMap of all widget-points on a model topology with the value being the "newDataDelFlag" for that spot.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, String> collectDeleteKeyHash( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ HashMap <String,String> currentHash, ArrayList <String> vidsTraversed,
+ int levelCounter, DbMaps dbMaps, HashMap <String, TitanVertex> modConstraintHash,
+ String overRideModelId, String overRideModelVersion )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectDeleteKeyHash");
+
+ HashMap <String, String> thisHash = new HashMap <String,String> ();
+ thisHash.putAll(currentHash);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectDeleteKeyHash() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+ HashMap <String, TitanVertex> modConstraintHash2Use = null;
+
+ // If this element represents a resource or service model, then we will replace this element with
+ // the "top" element of that resource or service model. That model-element already points to its
+ // topology, so it will graft in that model's topology.
+ // EXCEPT - if this element has "linkage-points" defined, then we need to do some extra
+ // processing for how we join to that model and will not try to go any "deeper".
+
+ //ArrayList <String> linkagePtList = thisLevelVertex.<ArrayList>property("linkage-points").orElse(null);
+ Object objVal = thisLevelVertex.property("linkage-points").orElse(null);
+ ArrayList <String> linkagePtList = makeSureItsAnArrayList( objVal );
+
+ if( linkagePtList != null && !linkagePtList.isEmpty() ){
+ // Whatever this element is - we are connecting to it via a linkage-point
+ // We will figure out what to do and then return without going any deeper
+ String elemFlag = thisLevelVertex.<String>property("new-data-del-flag").orElse(null);
+
+ HashSet <String> linkageConnectNodeTypes = getLinkageConnectNodeTypes( linkagePtList );
+ Iterator <?> linkNtIter = linkageConnectNodeTypes.iterator();
+ String incTrail = "";
+ if( !incomingTrail.equals("") ){
+ incTrail = incomingTrail + "|";
+ }
+
+ while( linkNtIter.hasNext() ){
+ // The 'trail' (or trails) for this element should just be the to the first-contact on the linkage point
+ String linkTrail = incTrail + linkNtIter.next();
+ Boolean alreadyTaggedFalse = false;
+ if( thisHash.containsKey(linkTrail) && thisHash.get(linkTrail).equals("F") ){
+ // some other path with a matching trail has the deleteFlag set to "F", so we do not want
+ // to override that since our model code only uses nodeTypes to know where it is - and we
+ // would rather do less deleting than needed instead of too much deleting.
+ alreadyTaggedFalse = true;
+ }
+ if( elemFlag != null && elemFlag.equals("T") && !alreadyTaggedFalse ){
+ // This trail should be marked with an "T"
+ thisHash.put(linkTrail, "T");
+ }
+ else {
+ thisHash.put(linkTrail, "F");
+ }
+ }
+ return thisHash;
+ }
+
+
+
+ // ---------------------------------------------------------------
+ // If we got to here, then this was not an element that used a linkage-point
+ // ---------------------------------------------------------------
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ // Even if this element is pointing to a service or resource model, it must have a
+ // first element which is a single widget-type model.
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+ String firstElementModelInfo = "";
+
+ vidsTraversed.add(thisVid);
+ TitanVertex elementVtxForThisLevel = null;
+ TitanVertex thisElementsModelVtx = getModelThatElementRepresents( thisLevelVertex, incomingTrail );
+ String modType = getModelType( thisElementsModelVtx, incomingTrail );
+
+ String subModelFirstModId = thisElementsModelVtx.<String>property("model-id").orElse(null);
+ String subModelFirstVersion = thisElementsModelVtx.<String>property("model-version").orElse(null);
+ if( modType.equals("widget") ){
+ if( overRideModelId != null && !overRideModelId.equals("") ){
+ // Note - this is just to catch the correct model for the TOP node in a model since
+ // it will have an element which will always be a widget even though the model
+ // could be a resource or service model.
+ firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersion;
+ }
+ }
+ else if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){
+ firstElementModelInfo = "," + subModelFirstModId + "," + subModelFirstVersion;
+ }
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType + firstElementModelInfo;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType + firstElementModelInfo;
+ }
+
+ String tmpFlag = "F";
+ Boolean stoppedByASvcOrResourceModelElement = false;
+ if( modType.equals("widget") ){
+ elementVtxForThisLevel = thisLevelVertex;
+ // For the element-model for the widget at this level, record it's delete flag
+ tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
+ }
+ else {
+ // For an element that is referring to a resource or service model, we replace this
+ // this element with the "top" element for that resource/service model so that the
+ // topology of that resource/service model gets included in this topology.
+ String modelUuid = thisElementsModelVtx.<String>property("model-name-version-id").orElse(null);
+ if( subModelFirstModId == null || subModelFirstModId.equals("")
+ || subModelFirstVersion == null || subModelFirstVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ // BUT -- if the model-element HERE at the resource/service level does NOT have
+ // it's new-data-del-flag set to "T", then we do not need to go down into the
+ // sub-model looking for delete-able things.
+
+ tmpFlag = thisLevelVertex.<String>property("new-data-del-flag").orElse(null);
+ elementVtxForThisLevel = getTopElementForSvcOrResModel(thisElementsModelVtx);
+ if( tmpFlag != null && tmpFlag.equals("T") ){
+ modConstraintHash2Use = getModConstraintHash( thisLevelVertex, modConstraintHash );
+ }
+ else {
+ stoppedByASvcOrResourceModelElement = true;
+ }
+ // For the element-model for the widget at this level, record it's delete flag
+ tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
+ }
+
+ String flag2Use = "F"; // by default we'll use "F" for the delete flag
+ if( ! stoppedByASvcOrResourceModelElement ){
+ // Since we haven't been stopped by a resource/service level "F", we can look at the lower level flag
+ if( thisHash.containsKey(thisGuysTrail) ){
+ // We've seen this spot in the topology before - do not override the delete flag if the older one is "F"
+ // We will only over-ride it if the old one was "T" and the new one is "F" (anything but "T")
+ String oldFlag = thisHash.get(thisGuysTrail);
+ if( oldFlag.equals("T") && (tmpFlag != null) && tmpFlag.equals("T") ){
+ // The old flag was "T" and the new flag is also "T"
+ flag2Use = "T";
+ }
+ else {
+ // the old flag was not "F" - so don't override it
+ flag2Use = "F";
+ }
+ }
+ else if( (tmpFlag != null) && tmpFlag.equals("T") ){
+ // We have not seen this one, so we can set it to "T" if that's what it is.
+ flag2Use = "T";
+ }
+ }
+
+ thisHash.put(thisGuysTrail, flag2Use);
+ if( ! stoppedByASvcOrResourceModelElement ){
+ // Since we haven't been stopped by a resource/service level "F", we will continue to
+ // go "down" and look at the elements pointed to so we can get their data.
+ Iterable <?> verts = elementVtxForThisLevel.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("model-element") ){
+ // A nice, regular old model-element
+ elementHash.put(vid, tmpVert);
+ }
+ else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // translate the constrained-element-set into a hash of model-element TitanVertex's
+ String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
+ if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
+ // This constrained-element-set is being superseded by a different one
+ TitanVertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
+ elementHash = getNextStepElementsFromSet( replacementConstraintVert );
+ // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
+ modConstraintHash.remove(constrainedElementSetUuid);
+ }
+ else {
+ elementHash = getNextStepElementsFromSet( tmpVert );
+ }
+ }
+ else {
+ String msg = " model element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ String tmpElNT = getElementWidgetType( elVert, thisGuysTrail );
+ check4EdgeRule(tmpElNT, thisElementNodeType, dbMaps);
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ HashMap <String, String> tmpHash = collectDeleteKeyHash( transId, fromAppId, graph,
+ elVert, thisGuysTrail,
+ currentHash, vidsTraversed, levelCounter, dbMaps, modConstraintHash2Use,
+ "", "" );
+ thisHash.putAll(tmpHash);
+ }
+ }
+ }
+ }
+ return thisHash;
+
+ } // End of collectDeleteKeyHash()
+
+
+ /**
+ * Gets the linkage connect node types.
+ *
+ * @param linkagePtList the linkage pt list
+ * @return the linkage connect node types
+ * @throws AAIException the AAI exception
+ */
+ public static HashSet <String> getLinkageConnectNodeTypes( ArrayList <String> linkagePtList )
+ throws AAIException {
+ // linkage points are a path from the top of a model to where we link in.
+ // This method wants to just bring back a list of distinct last items.
+ // Ie: for the input with these two: "pserver|lag-link|l-interface" and "pserver|p-interface|l-interface"
+ // it would just return a single item, "l-interface" since both linkage points end in that same node-type.
+
+ HashSet <String> linkPtSet = new HashSet <String> ();
+
+ if( linkagePtList == null ){
+ String detail = " Bad (null) linkagePtList passed to getLinkageConnectNodeTypes() ";
+ throw new AAIException("AAI_6125", detail);
+ }
+
+ for( int i = 0; i < linkagePtList.size(); i++ ){
+ String [] trailSteps = linkagePtList.get(i).split("\\|");
+ if( trailSteps == null || trailSteps.length == 0 ){
+ String detail = " Bad incomingTrail passed to getLinkageConnectNodeTypes(): [" + linkagePtList + "] ";
+ throw new AAIException("AAI_6125", detail);
+ }
+ String lastStepNT = trailSteps[trailSteps.length - 1];
+ linkPtSet.add(lastStepNT);
+ }
+
+ return linkPtSet;
+
+ }// End getLinkageConnectNodeTypes()
+
+
+ /**
+ * Collect topology 4 model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param modelElement vertex to collect for
+ * @param incomingTrail the incoming trail -- trail of nodeTypes/personnaInfo that got us here (this vertex) from the top
+ * @param currentMap the current map -- map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param dbMaps the db maps
+ * @param modConstraintHash the mod constraint hash
+ * @param overRideModelId the over ride model id
+ * @param overRideModelVersion the over ride model version
+ * @return Map of the topology
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4Model( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ Multimap <String,String> currentMap, ArrayList <String> vidsTraversed,
+ int levelCounter, DbMaps dbMaps, HashMap <String, TitanVertex> modConstraintHash,
+ String overRideModelId, String overRideModelVersion )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4Model");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectTopology4Model() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+ HashMap <String, TitanVertex> modConstraintHash2Use = null;
+
+
+ // If this element represents a resource or service model, then we will replace this element with
+ // the "top" element of that resource or service model. That model-element already points to its
+ // topology, so it will graft in that model's topology.
+ // EXCEPT - if this element defines "linkage-points" defined, then we need to do some extra
+ // processing for how we join to that model.
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ // Even if this element is pointing to a service or resource model, it must have a
+ // first element which is a single widget-type model.
+ String firstElementModelInfo = "";
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+ if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) && overRideModelId != null && !overRideModelId.equals("") ){
+ firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersion;
+ }
+
+ vidsTraversed.add(thisVid);
+ TitanVertex elementVtxForThisLevel = null;
+ TitanVertex thisElementsModelVtx = getModelThatElementRepresents( thisLevelVertex, incomingTrail );
+ String subModelFirstModId = "";
+ String subModelFirstVersion = "";
+ String modInfo4Trail = "";
+ String modType = getModelType( thisElementsModelVtx, incomingTrail );
+ if( modType.equals("resource") || modType.equals("service") ){
+ // For an element that is referring to a resource or service model, we replace this
+ // this element with the "top" element for that resource/service model so that the
+ // topology of that resource/service model gets included in this topology.
+ // -- Note - since that top element of a service or resource model will point to a widget model,
+ // we have to track what modelId/version it really maps so we can make our recursive call
+ subModelFirstModId = thisElementsModelVtx.<String>property("model-id").orElse(null);
+ subModelFirstVersion = thisElementsModelVtx.<String>property("model-version").orElse(null);
+ modInfo4Trail = "," + subModelFirstModId + "," + subModelFirstVersion;
+ String modelUuid = thisElementsModelVtx.<String>property("model-name-version-id").orElse(null);
+ if( subModelFirstModId == null || subModelFirstModId.equals("") || subModelFirstVersion == null || subModelFirstVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+ elementVtxForThisLevel = getTopElementForSvcOrResModel(thisElementsModelVtx);
+ modConstraintHash2Use = getModConstraintHash( thisLevelVertex, modConstraintHash );
+ }
+ else {
+ elementVtxForThisLevel = thisLevelVertex;
+ }
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType + firstElementModelInfo;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail;
+ }
+
+ // Look at the elements pointed to at this level and add on their data
+ Iterable <?> verts = elementVtxForThisLevel.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("model-element") ){
+ // A nice, regular old model-element
+ elementHash.put(vid, tmpVert);
+ }
+ else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // translate the constrained-element-set into a hash of model-element TitanVertex's
+ String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
+ if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
+ // This constrained-element-set is being superseded by a different one
+ TitanVertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
+ elementHash = getNextStepElementsFromSet( replacementConstraintVert );
+ // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
+ modConstraintHash.remove(constrainedElementSetUuid);
+ }
+ else {
+ elementHash = getNextStepElementsFromSet( tmpVert );
+ }
+ }
+ else {
+ String msg = " model element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ String tmpElNT = getElementWidgetType( elVert, thisGuysTrail );
+ String tmpElStepName = getElementStepName( elVert, thisGuysTrail, dbMaps );
+
+ //ArrayList <String> linkagePtList = elVert.<ArrayList>property("linkage-points").orElse(null);
+ Object objVal = elVert.property("linkage-points").orElse(null);
+ ArrayList <String> linkagePtList = makeSureItsAnArrayList( objVal );
+
+ if( linkagePtList != null && !linkagePtList.isEmpty() ){
+ // This is as far as we can go, we will use the linkage point info to define the
+ // rest of this "trail"
+ for( int i = 0; i < linkagePtList.size(); i++ ){
+ Multimap<String, String> tmpMap = collectTopology4LinkagePoint( transId, fromAppId,
+ linkagePtList.get(i), thisGuysTrail, currentMap, dbMaps);
+ thisMap.putAll(tmpMap);
+ }
+ }
+ else {
+ check4EdgeRule(tmpElNT, thisElementNodeType, dbMaps);
+ thisMap.put(thisGuysTrail, tmpElStepName);
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ Multimap<String, String> tmpMap = collectTopology4Model( transId, fromAppId, graph,
+ elVert, thisGuysTrail,
+ currentMap, vidsTraversed, levelCounter,
+ dbMaps, modConstraintHash2Use, subModelFirstModId, subModelFirstVersion );
+ thisMap.putAll(tmpMap);
+ }
+ else {
+ String msg = "Bad Model Definition: looping model-elements found at: [" + tmpElStepName + "]." ;
+ System.out.println( msg );
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+ }
+ }
+ return thisMap;
+
+ } // End of collectTopology4Model()
+
+
+ /**
+ * Check 4 edge rule.
+ *
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @param dbMaps the db maps
+ * @throws AAIException the AAI exception
+ */
+ public static void check4EdgeRule( String nodeTypeA, String nodeTypeB, DbMaps dbMaps ) throws AAIException {
+ // Throw an exception if there is no defined edge rule for this combination of nodeTypes in DbEdgeRules.
+ String fwdRuleKey = nodeTypeA + "|" + nodeTypeB;
+ String revRuleKey = nodeTypeB + "|" + nodeTypeA;
+ if( !DbEdgeRules.EdgeRules.containsKey(fwdRuleKey)
+ && !DbEdgeRules.EdgeRules.containsKey(revRuleKey) ){
+ // There's no EdgeRule for this -- find out if one of the nodeTypes is invalid or if
+ // they are valid, but there's just no edgeRule for them.
+ if( ! dbMaps.NodeProps.containsKey(nodeTypeA) ){
+ String emsg = " Unrecognized nodeType aa [" + nodeTypeA + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+ else if( ! dbMaps.NodeProps.containsKey(nodeTypeB) ){
+ String emsg = " Unrecognized nodeType bb [" + nodeTypeB + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+ else {
+ String msg = " No Edge Rule found for this pair of nodeTypes (order does not matter) ["
+ + nodeTypeA + "], [" + nodeTypeB + "].";
+ throw new AAIException("AAI_6120", msg);
+ }
+ }
+
+ }
+
+
+ /**
+ * Collect topology 4 linkage point.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param linkagePointStr -- Note it is in reverse order from where we connect to it.
+ * @param incomingTrail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param currentMap the current map -- that got us to this point (that we will use as the base of the map we will return)
+ * @param dbMaps the db maps
+ * @return Map of the topology
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4LinkagePoint( String transId, String fromAppId,
+ String linkagePointStr, String incomingTrail, Multimap <String,String> currentMap, DbMaps dbMaps )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4LinkagePoint");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+ String thisGuysTrail = incomingTrail;
+ // NOTE - "trails" can have multiple parts now since we track persona info for some.
+ // We just want to look at the node type info - which would be the piece
+ // before any commas (if there are any).
+ String [] trailSteps = incomingTrail.split("\\|");
+ if( trailSteps == null || trailSteps.length == 0 ){
+ String detail = " Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", detail);
+ }
+ String lastStepString = trailSteps[trailSteps.length - 1];
+ String [] stepPieces = lastStepString.split(",");
+ String lastStepNT = stepPieces[0];
+ // It is assumed that the linkagePoint string will be a pipe-delimited string where each
+ // piece is an "aai-node-type". For now, the first thing to connect to is what is on the farthest right.
+ // Example: linkagePoint = "pserver|p-interface|l-interface" would mean that we're connecting to the l-interface
+ // but that after that, we connect to a p-interface followed by a pserver.
+ // It might have been more clear to define it in the other direction, but for now, that is it. (16-07)
+
+ String thisStepNT = "";
+ String [] linkageSteps = linkagePointStr.split("\\|");
+
+ if( linkageSteps == null || linkageSteps.length == 0 ){
+ String detail = " Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + linkagePointStr + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", detail);
+ }
+
+ for( int i=(linkageSteps.length - 1); i >= 0; i-- ){
+ thisStepNT = linkageSteps[i];
+ check4EdgeRule(lastStepNT, thisStepNT, dbMaps);
+ thisMap.put(thisGuysTrail, thisStepNT);
+ thisGuysTrail = thisGuysTrail + "|" + thisStepNT;
+ lastStepNT = thisStepNT;
+ }
+
+ return thisMap;
+
+ } // End of collectTopology4LinkagePoint()
+
+
+
+ /**
+ * Gets the next step elements from set.
+ *
+ * @param constrElemSetVtx the constr elem set vtx
+ * @return Hash of the set of model-elements this set represents
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNextStepElementsFromSet( TitanVertex constrElemSetVtx )
+ throws AAIException {
+ // Take a constrained-element-set and figure out the total set of all the possible elements that it
+ // represents and return them as a Hash.
+
+ HashMap <String,Object> retElementHash = new HashMap<String, Object>();
+
+ if( constrElemSetVtx == null ){
+ String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx ";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ String constrNodeType = constrElemSetVtx.<String>property("aai-node-type").orElse(null);
+ String constrElemSetUuid = constrElemSetVtx.<String>property("constrained-element-set-uuid").orElse(null);
+ if( constrNodeType == null || !constrNodeType.equals("constrained-element-set") ){
+ String msg = " getNextStepElementsFromSet() called with wrong type model: [" + constrNodeType + "]. ";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ ArrayList <TitanVertex> choiceSetVertArray = new ArrayList<TitanVertex>();
+
+ Iterable <?> choiceSetVerts = constrElemSetVtx.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> vertI = choiceSetVerts.iterator();
+ int setCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex choiceSetVertex = (TitanVertex) vertI.next();
+ String constrSetType = choiceSetVertex.<String>property("aai-node-type").orElse(null);
+ if( constrSetType != null && constrSetType.equals("element-choice-set") ){
+ choiceSetVertArray.add(choiceSetVertex);
+ setCount++;
+ }
+ }
+
+ if( setCount == 0 ){
+ String msg = "No element-choice-set found under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ // Loop through each choice-set and grab the model-elements
+ for( int i = 0; i < setCount; i++ ){
+ Iterable <?> modelElemVerts = (choiceSetVertArray.get(i)).query().direction(Direction.OUT).labels("has").vertices();
+ Iterator <?> mVertI = modelElemVerts.iterator();
+ int elCount = 0;
+ while( mVertI != null && mVertI.hasNext() ){
+ TitanVertex tmpElVertex = (TitanVertex) mVertI.next();
+ String elNodeType = tmpElVertex.<String>property("aai-node-type").orElse(null);
+ if( elNodeType != null && elNodeType.equals("model-element") ){
+ String tmpVid = tmpElVertex.id().toString();
+ retElementHash.put(tmpVid, tmpElVertex);
+ elCount++;
+ }
+ else {
+ // unsupported node type found for this choice-set
+ String msg = "Unsupported nodeType (" + elNodeType
+ + ") found under choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+
+ if( elCount == 0 ){
+ String msg = "No model-elements found in choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }
+ return retElementHash;
+
+ } // End of getNextStepElementsFromSet()
+
+
+
+ /**
+ * Gen topo map 4 named Q.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param queryVertex the query vertex
+ * @param namedQueryUuid the named query uuid
+ * @return MultiMap of valid next steps for each potential query-element
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> genTopoMap4NamedQ( String transId, String fromAppId,
+ TitanTransaction graph, TitanVertex queryVertex, String namedQueryUuid )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "genTopoMap4NamedQ");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to genTopoMap4NamedQ()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( queryVertex == null ){
+ String msg = " null queryVertex passed to genTopoMap4NamedQ() ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ Multimap <String, String> initialEmptyMap = ArrayListMultimap.create();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+
+ TitanVertex firstElementVertex = null;
+ Iterable <?> verts = queryVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ int elCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ elCount++;
+ firstElementVertex = (TitanVertex) vertI.next();
+ }
+
+ if( elCount > 1 ){
+ String msg = "Illegal query defined: More than one first element defined for = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ if( firstElementVertex == null ){
+ String msg = "Could not find first query element = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6144");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ TitanVertex modVtx = getModelThatElementRepresents( firstElementVertex, "" );
+ String modelType = getModelType( modVtx, "" );
+ if( ! modelType.equals("widget") ){
+ String msg = "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = "
+ + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ Multimap <String, String> collectedMap = collectTopology4NamedQ( transId, fromAppId, graph,
+ firstElementVertex, "",
+ initialEmptyMap, vidsTraversed, 0);
+
+ return collectedMap;
+
+ } // End of genTopoMap4NamedQ()
+
+
+
+ /**
+ * Collect topology 4 named Q.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param levelCounter the level counter
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4NamedQ( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ Multimap <String,String> currentMap, ArrayList <String> vidsTraversed, int levelCounter )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4NamedQ");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+
+ String thisVid = thisLevelVertex.id().toString();
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectModelStructure() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+
+ // find out what widget-model (and thereby what aai-node-type) this element represents
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
+ }
+ vidsTraversed.add(thisVid);
+
+ // Look at the elements pointed to at this level and add on their data
+ Iterable <?> verts = thisLevelVertex.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String tmpVid = tmpVert.id().toString();
+ String tmpElNT = getElementWidgetType( tmpVert, thisGuysTrail );
+ thisMap.put(thisGuysTrail, tmpElNT);
+ if( !vidsTraversed.contains(tmpVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ Multimap<String, String> tmpMap = collectTopology4NamedQ( transId, fromAppId, graph,
+ tmpVert, thisGuysTrail,
+ currentMap, vidsTraversed, levelCounter);
+ thisMap.putAll(tmpMap);
+ }
+ }
+
+ return thisMap;
+
+ } // End of collectTopology4NamedQ()
+
+
+ /**
+ * Gets the model that element represents.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @return the model that element represents
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelThatElementRepresents( TitanVertex elementVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the model that an element represents
+ TitanVertex modVtx = null;
+ Iterable <?> mverts = elementVtx.query().direction(Direction.OUT).labels("isA").vertices();
+ Iterator <?> mvertI = mverts.iterator();
+ int modCount = 0;
+ while( mvertI != null && mvertI.hasNext() ){
+ modCount++;
+ modVtx = (TitanVertex) mvertI.next();
+ }
+
+ if( modCount > 1 ){
+ String msg = "Illegal element defined: More than one model pointed to by a single element at [" +
+ elementTrail + "].";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ if( modVtx == null ){
+ String msg = "Bad model or named-query definition: Could not find model for element. ";
+ if( !elementTrail.equals("") ){
+ msg = "Bad model or named-query definition: Could not find model for element at [" + elementTrail + "].";
+ }
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return modVtx;
+
+ }// getModelThatElementRepresents()
+
+
+ /**
+ * Gets the model type.
+ *
+ * @param modelVtx the model vtx
+ * @param elementTrail the element trail
+ * @return the model type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelType( TitanVertex modelVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the model-type for a vertex that should be pointing to a model.
+
+ if( modelVtx == null ){
+ String msg = " null modelVtx passed to getModelType() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelVtx.<String>property("model-type").orElse(null);
+ if( (modelType == null) || modelType.equals("") ){
+ String msg = "Could not find model-type for model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){
+ String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return modelType;
+
+ }// getModelType()
+
+
+ /**
+ * Gets the element step name.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @param dbMaps the db maps
+ * @return the element step name
+ * @throws AAIException the AAI exception
+ */
+ public static String getElementStepName( TitanVertex elementVtx, String elementTrail, DbMaps dbMaps)
+ throws AAIException {
+
+ // Get the "step name" for either a model-element or a named-query-element.
+ // Step names look like this for widget-models: "aai-node-type"
+ // Step names look like this for resource/service models: "aai-node-type,model-id,model-version"
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+ String thisElementNodeType = "?";
+
+ TitanVertex modVtx = getModelThatElementRepresents( elementVtx, elementTrail );
+ String modelType = getModelType( modVtx, elementTrail );
+
+ if( modelType == null ){
+ String msg = " Null modelType passed to getElementWidgetType(). elementTrail = [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( modelType.equals("widget") ){
+ // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type
+ thisElementNodeType = modVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ return thisElementNodeType;
+ }
+ else if( modelType.equals("resource") || modelType.equals("service") ){
+ String modelId = modVtx.<String>property("model-id").orElse(null);
+ String modelVer = modVtx.<String>property("model-version").orElse(null);
+ TitanVertex relatedTopElementModelVtx = getTopElementForSvcOrResModel( modVtx );
+ TitanVertex relatedModelVtx = getModelThatElementRepresents( relatedTopElementModelVtx, elementTrail );
+ thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null);
+
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ String stepName = "";
+ if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){
+ // This nodeType that this resource or service model refers to does support persona-related fields, so
+ // we will use model-id and model-version as part of the step name.
+ stepName = thisElementNodeType + "," + modelId + "," + modelVer;
+ }
+ else {
+ stepName = thisElementNodeType;
+ }
+ return stepName;
+ }
+ else {
+ String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }// getElementStepName()
+
+
+
+ /**
+ * Node type supports persona.
+ *
+ * @param nodeType the node type
+ * @param dbMaps the db maps
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean nodeTypeSupportsPersona(String nodeType, DbMaps dbMaps)
+ throws AAIException {
+
+ if( nodeType == null || nodeType.equals("") ){
+ return false;
+ }
+
+ // Return true if this type of node supports the properties: "persona-model-id" and "persona-model-version"
+ if( ! dbMaps.NodeProps.containsKey(nodeType) ){
+ String emsg = " Unrecognized nodeType [" + nodeType + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+
+ Collection <String> props4ThisNT = dbMaps.NodeProps.get(nodeType);
+ if( !props4ThisNT.contains("persona-model-id") || !props4ThisNT.contains("persona-model-version") ){
+ return false;
+ }
+ else {
+ return true;
+ }
+
+ }// nodeTypeSupportsPersona()
+
+
+ /**
+ * Gets the element widget type.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @return the element widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getElementWidgetType( TitanVertex elementVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the associated node-type for the model pointed to by either a
+ // model-element or a named-query-element.
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+ TitanVertex modVtx = getModelThatElementRepresents( elementVtx, elementTrail );
+ String thisElementNodeType = getModelWidgetType( modVtx, elementTrail );
+ return thisElementNodeType;
+
+ }// End getElementWidgetType()
+
+
+ /**
+ * Gets the mod name ver id.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modId the mod id
+ * @param modVersion the mod version
+ * @return the mod name ver id
+ * @throws AAIException the AAI exception
+ */
+ public static String getModNameVerId(String transId, String fromAppId, TitanTransaction graph,
+ String modId, String modVersion)
+ throws AAIException {
+
+ String modelNameVersionId = "";
+
+ // Given a "model-id" and "model-version", find the unique key ("model-name-version-id") for this model
+ if( modId == null || modId.equals("") || modVersion == null || modVersion.equals("") ){
+ String emsg = " Bad model-id or model-version passed to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",modId).has("model-version",modVersion).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. (model-id = [" + modId +
+ "], model-version = [" + modVersion + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ int count = 0;
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ count++;
+ TitanVertex tmpModVtx = (TitanVertex) modVertsIter.next();
+ modelNameVersionId = tmpModVtx.<String>property("model-name-version-id").orElse(null);
+ if( count > 1 ){
+ String emsg = "More than one model-name-version-id found for passed params to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( modelNameVersionId.equals("") ){
+ String emsg = "Could not find a model-name-version-id for passed params to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelNameVersionId;
+ }// End getModNameVerId()
+
+
+ /**
+ * Gets the model using UUID.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @return the model using UUID
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelUsingUUID( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId )
+ throws AAIException {
+
+ // Given a "model-name-version-id", find the model vertex that this uniquely maps to
+ if( modelNameVersionId == null || modelNameVersionId.equals("") ){
+ String emsg = " Bad modelNameVersionId passed to getModNameVerId(): ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ TitanVertex modelVtx = null;
+ int count = 0;
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name-version-id",modelNameVersionId).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name-version-id = [" + modelNameVersionId +
+ "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ count++;
+ modelVtx = (TitanVertex) modVertsIter.next();
+ if( count > 1 ){
+ String emsg = "More than one model record found for model-name-version-id = ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( count == 0 ){
+ String emsg = "No Model record found for model-name-version-id = ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelVtx;
+ }// End getModelUsingUUID()
+
+
+ /**
+ * Gets the model using persona info.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param personaModId the persona mod id
+ * @param personaModVer the persona mod ver
+ * @return the model using persona info
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelUsingPersonaInfo( String transId, String fromAppId, TitanTransaction graph,
+ String personaModId, String personaModVer )
+ throws AAIException {
+
+ // Given a model-id and model-version, find the model vertex that this uniquely maps to
+ if( personaModId == null || personaModId.equals("") ){
+ String emsg = " Bad personaModId passed to getModelUsingPersonaInfo(): ["
+ + personaModId + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+ if( personaModVer == null || personaModVer.equals("") ){
+ String emsg = " Bad personaModVer passed to getModelUsingPersonaInfo(): ["
+ + personaModVer + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ TitanVertex modelVtx = null;
+ int modCount = 0;
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",personaModId).has("model-version",personaModVer).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ modCount++;
+ modelVtx = (TitanVertex) modVertsIter.next();
+ if( modCount > 1 ){
+ String emsg = "More than one model record found for persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]. ";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( modCount == 0 ){
+ String emsg = "No Model record found for persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]. ";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelVtx;
+ }// End getModelUsingPersonaInfo()
+
+
+
+ /**
+ * Gets the models using name.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelName the model name
+ * @return the models using name
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <TitanVertex> getModelsUsingName( String transId, String fromAppId, TitanTransaction graph,
+ String modelName )
+ throws AAIException {
+
+ // Given a "model-name", find the model vertices that this maps to
+ if( modelName == null || modelName.equals("") ){
+ String emsg = " Bad modelName passed to getModelsUsingName(): ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList <TitanVertex> retVtxArr = new ArrayList <TitanVertex> ();
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name = [" +
+ modelName + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex tmpModelVtx = (TitanVertex) modVertsIter.next();
+ retVtxArr.add(tmpModelVtx);
+ }
+ }
+
+ return retVtxArr;
+
+ }// End getModelsUsingName()
+
+
+ /**
+ * Gets the model uuids using name.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelName the model name
+ * @return the model uuids using name
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <String> getModelUuidsUsingName( String transId, String fromAppId, TitanTransaction graph,
+ String modelName )
+ throws AAIException {
+
+ // Given a modelName find the models maps to
+ if( modelName == null || modelName.equals("") ){
+ String emsg = " Bad modelName passed to getModelUuidsUsingName(): ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name = [" +
+ modelName + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex modelVtx = (TitanVertex) modVertsIter.next();
+ String tmpUuid = modelVtx.<String>property("model-name-version-id").orElse(null);
+ if( (tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid) ){
+ retArr.add(tmpUuid);
+ }
+ }
+ }
+
+ if( retArr.isEmpty() ){
+ String emsg = "No Model record found for model-name = ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return retArr;
+ }// End getModelUuidsUsingName()
+
+
+ /**
+ * Gets the model top widget type.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param modelId the model id
+ * @param modelName the model name
+ * @return the model top widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelTopWidgetType( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId, String modelId, String modelName )
+ throws AAIException {
+
+ // Could be given a model's key info, OR, just a (non-unique) modelId.
+ // Either way, they should only map to one single "top" node-type for the first element.
+
+ String nodeType = "?";
+ Iterable <?> modVerts = null;
+ if( modelNameVersionId != null && !modelNameVersionId.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-name-version-id",modelNameVersionId).vertices();
+ }
+ else if( modelId != null && !modelId.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",modelId).vertices();
+ }
+ else if( modelName != null && !modelName.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ }
+ else {
+ String msg = "Neither modelNameVersionId, modelId, nor modelName passed to: getModelTopWidgetType() ";
+ throw new AAIException("AAI_6120", msg);
+ }
+
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. (modelId = [" + modelId +
+ "], modelNameVersionId = [" + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ String lastNT = "";
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex tmpModVtx = (TitanVertex) modVertsIter.next();
+ String tmpNT = getModelWidgetType( tmpModVtx, "" );
+ if( !lastNT.equals("") ){
+ if( !lastNT.equals(tmpNT) ){
+ String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT
+ + ") found for model data passed. (" +
+ " modelNameVersionId = [" + modelNameVersionId +
+ "], modelId = [" + modelId +
+ "], modelName = [" + modelName +
+ "])\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ }
+ lastNT = tmpNT;
+ nodeType = tmpNT;
+ }
+ }
+
+ return nodeType;
+
+ }// End getModelTopWidgetType()
+
+
+ /**
+ * Gets the model widget type.
+ *
+ * @param modVtx the mod vtx
+ * @param elementTrail the element trail
+ * @return the model widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelWidgetType( TitanVertex modVtx, String elementTrail )
+ throws AAIException {
+ // Get the associated node-type for a model.
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+
+ String modelType = getModelType( modVtx, elementTrail );
+ if( modelType == null ){
+ String msg = " Null modelType passed to getElementWidgetType(). elementTrail = [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String thisElementNodeType = "?";
+ if( modelType.equals("widget") ){
+ // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type
+ thisElementNodeType = modVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }
+ else if( modelType.equals("resource") || modelType.equals("service") ){
+ TitanVertex relatedTopElementModelVtx = getTopElementForSvcOrResModel( modVtx );
+ TitanVertex relatedModelVtx = getModelThatElementRepresents( relatedTopElementModelVtx, elementTrail );
+ thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+ else {
+ String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return thisElementNodeType;
+
+ }// getModelWidgetType()
+
+
+ /**
+ * Validate model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ public static void validateModel(String transId, String fromAppId, TitanTransaction graph, String modelNameVersionId, String apiVersion )
+ throws AAIException{
+
+ // Note - this will throw an exception if the model either can't be found, or if
+ // we can't figure out its topology map.
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "model-name-version-id", modelNameVersionId );
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ TitanVertex modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash, null, apiVersion);
+ if( modelVtx == null ){
+ String msg = " Could not find model with modelNameVersionId = [" + modelNameVersionId + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ Multimap<String, String> topoMap = ModelBasedProcessing.genTopoMap4Model( transId, fromAppId, graph,
+ modelVtx, modelNameVersionId, dbMaps );
+ //String msg = " model [" + modelNameVersionId + "] topo multiMap looks like: \n[" + topoMap + "]";
+ //System.out.println("INFO -- " + msg );
+ }
+ return;
+
+ }// End validateModel()
+
+
+ /**
+ * Validate named query.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ public static void validateNamedQuery(String transId, String fromAppId, TitanTransaction graph, String namedQueryUuid, String apiVersion )
+ throws AAIException{
+
+ // Note - this will throw an exception if the named query either can't be found, or if
+ // we can't figure out its topology map.
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "named-query-uuid", namedQueryUuid );
+
+ TitanVertex modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash, null, apiVersion);
+ if( modelVtx == null ){
+ String msg = " Could not find model with namedQueryUuid = [" + namedQueryUuid + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ Multimap<String, String> topoMap = ModelBasedProcessing.genTopoMap4NamedQ( "junkTransId", "junkFromAppId",
+ graph, modelVtx, namedQueryUuid );
+ //String msg = " namedQuery [" + namedQueryUuid + "] topo multiMap looks like: \n[" + topoMap + "]";
+ //System.out.println("INFO -- " + msg );
+ }
+ return;
+
+ }// End validateNamedQuery()
+
+
+ public static ArrayList <String> makeSureItsAnArrayList( Object objVal ){
+ // We're sometimes getting a String back on db properties that should be ArrayList<String>
+ // Need to translate them into ArrayLists sometimes...
+
+ ArrayList <String> retArrList = new ArrayList<String>();
+ if( objVal != null ){
+ String className = objVal.getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ retArrList = (ArrayList<String>)objVal;
+ }
+ else if( className.equals("String") ){
+ String listString = (String) objVal;
+ listString = listString.replace(" ", "");
+ listString = listString.replace("[", "");
+ listString = listString.replace("]", "");
+ String [] pieces = listString.split(",");
+ if( pieces != null && pieces.length > 0 ){
+ for( int i = 0; i < pieces.length; i++ ){
+ retArrList.add(pieces[i]);
+ }
+ }
+ }
+ }
+
+ return retArrList;
+ }
+
+
+
+ /**
+ * Show result set.
+ *
+ * @param resSet the res set
+ * @param levelCount the level count
+ */
+ public static void showResultSet( ResultSet resSet, int levelCount ) {
+
+ levelCount++;
+ for( int i= 1; i <= levelCount; i++ ){
+ System.out.print("-");
+ }
+ if( resSet.vert == null ){
+ return;
+ }
+ String nt = resSet.vert.<String>property("aai-node-type").orElse(null);
+ System.out.print( "[" + nt + "] ");
+ String propsStr = "";
+
+ //propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + resSet.getLocationInModelSubGraph();
+ //propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]";
+ propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph();
+
+ HashMap <String,Object> overrideHash = resSet.getPropertyOverRideHash();
+ if( overrideHash != null && !overrideHash.isEmpty() ){
+ for( Map.Entry<String, Object> entry : overrideHash.entrySet() ){
+ String propName = entry.getKey();
+ Object propVal = entry.getValue();
+ propsStr = propsStr + " [" + propName + " = " + propVal + "]";
+ }
+ }
+ else {
+ Iterator<VertexProperty<Object>> pI = resSet.vert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ if( ! tp.key().startsWith("aai")
+ && ! tp.key().equals("source-of-truth")
+ //&& ! tp.key().equals("resource-version")
+ && ! tp.key().startsWith("last-mod")
+ )
+ {
+ propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]";
+ }
+ }
+ }
+ // Show the "extra" lookup values too
+ HashMap <String,Object> extraPropHash = resSet.getExtraPropertyHash();
+ if( extraPropHash != null && !extraPropHash.isEmpty() ){
+ for( Map.Entry<String, Object> entry : extraPropHash.entrySet() ){
+ String propName = entry.getKey();
+ Object propVal = entry.getValue();
+ propsStr = propsStr + " [" + propName + " = " + propVal.toString() + "]";
+ }
+ }
+
+ System.out.println( propsStr );
+
+ if( !resSet.subResultSet.isEmpty() ){
+ ListIterator<ResultSet> listItr = resSet.subResultSet.listIterator();
+ while( listItr.hasNext() ){
+ showResultSet( listItr.next(), levelCount );
+ }
+ }
+
+ }// end of showResultSet()
+
+
+}
+