2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.dbgraphgen;
22 import com.att.eelf.configuration.EELFLogger;
23 import com.att.eelf.configuration.EELFManager;
24 import com.google.common.collect.ArrayListMultimap;
25 import com.google.common.collect.Multimap;
26 import com.google.common.util.concurrent.SimpleTimeLimiter;
27 import com.google.common.util.concurrent.TimeLimiter;
28 import com.google.common.util.concurrent.UncheckedTimeoutException;
29 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
30 import org.apache.tinkerpop.gremlin.structure.Vertex;
31 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
32 import org.onap.aai.db.DbMethHelper;
33 import org.onap.aai.db.props.AAIProperties;
34 import org.onap.aai.dbgen.PropertyLimitDesc;
35 import org.onap.aai.exceptions.AAIException;
36 import org.onap.aai.introspection.Introspector;
37 import org.onap.aai.introspection.Loader;
38 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
39 import org.onap.aai.query.builder.QueryBuilder;
40 import org.onap.aai.schema.enums.PropertyMetadata;
41 import org.onap.aai.serialization.db.DBSerializer;
42 import org.onap.aai.serialization.db.EdgeRules;
43 import org.onap.aai.serialization.db.EdgeType;
44 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
45 import org.onap.aai.util.AAIConfig;
48 import java.util.concurrent.Callable;
49 import java.util.concurrent.TimeUnit;
52 * Utility class that uses Model/Named-Query definitions to navigate the graph.
54 public class ModelBasedProcessing {
56 private EELFLogger LOGGER = EELFManager.getInstance().getLogger(ModelBasedProcessing.class);
57 private final int MAX_LEVELS = 50; // max depth allowed for our model - to protect against infinite loop problems
59 private TransactionalGraphEngine engine;
60 private Loader loader;
61 private DBSerializer serializer;
62 private DbMethHelper dbMethHelper;
64 protected ModelBasedProcessing() {
67 public ModelBasedProcessing(Loader loader, TransactionalGraphEngine engine, DBSerializer serializer) {
70 this.serializer = serializer;
71 dbMethHelper = new DbMethHelper(loader, engine);
74 * Gets the start nodes and model-ver's.
76 * @param transId the trans id
77 * @param fromAppId the from app id
78 * @param passedModelVersionId the passed model-version-id -- optional (unique id for a model-ver)
79 * @param passedModelId the passed model-invariant-id -- optional
80 * @param passedModelName the passed model-name -- optional
81 * @param passedTopNodeType the passed top node type -- optional (needed if neither model=invariant-id nor model-version-id is passed)
82 * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
83 * @param apiVer the api ver
84 * @return HashMap of startNodes and their corresponding model-version-id's
85 * @throws AAIException the AAI exception
87 public Map<String,String> getStartNodesAndModVersionIds( String transId, String fromAppId,
88 String passedModelVersionId,
89 String passedModelInvId,
90 String passedModelName,
91 String passedTopNodeType,
92 List<Map<String,Object>> startNodeFilterArrayOfHashes,
95 // ----------------------------------------------------------------------------------------------------
96 // Get a hash for all start-nodes (key = vtxId, val = modelVersionId that applies)
97 // If no start-node-key info is passed, then use either the passed modelVersion or
98 // the passed model-invariant-id or model-name to collect them.
99 // If start-node-key info is given, use it instead to look for start-nodes.
100 // Note: if ONLY start-node-key info is given, then it would have to map to nodes which
101 // have persona data. Otherwise we'd have no way to know what model to collect data with.
102 // ----------------------------------------------------------------------------------------------------
104 Iterator<Vertex> startVerts = null;
105 Map<String, String> startVertInfo = new HashMap<>();
107 if( startNodeFilterArrayOfHashes.isEmpty() ){
108 // Since they did not give any data to find start instances, we will have to find them
109 // using whatever model-info they provided so we can use it to map to persona-data in the db.
110 if( (passedModelVersionId == null || passedModelVersionId.equals(""))
111 && (passedModelInvId == null || passedModelInvId.equals(""))
112 && (passedModelName == null || passedModelName.equals(""))){
113 throw new AAIException("AAI_6118", "ModelInvariantId or ModelName or ModelVersionId required if no startNodeFilter data passed.");
116 // Use whatever model info they pass to find start-node instances
117 // Get the first/top named-query-element used by this query
118 if( passedModelVersionId != null && !passedModelVersionId.equals("") ){
119 // Need to look up the model-invariant-id and model-version to check against persona data
120 Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver",
121 "model-version-id", passedModelVersionId);
122 Vertex modVtx = getModelGivenModelVer( modVerVtx, "" );
123 String calcModId = modVtx.<String>property("model-invariant-id").orElse(null);
124 // Now we can look up instances that match this model's info
125 if( calcModId != null ){
126 startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),calcModId).has(addDBAliasedSuffix("model-version-id"),passedModelVersionId);
129 else if( passedModelInvId != null && !passedModelInvId.equals("") ){
130 // They gave us the model-invariant-id
131 startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),passedModelInvId);
133 else if( passedModelName != null && !passedModelName.equals("") ){
134 List<Vertex> modelVerVtxList = getModelVersUsingName(transId, fromAppId, passedModelName);
135 List<Vertex> startVtxList = new ArrayList<>();
136 // Need to look up the model-inv-ids and model-versions to check against persona data
137 if( !modelVerVtxList.isEmpty() ){
138 for( int i = 0; i < modelVerVtxList.size(); i++ ){
139 String calcModVerId = (modelVerVtxList.get(i)).<String>property("model-version-id").orElse(null);
140 Vertex modVtx = getModelGivenModelVer(modelVerVtxList.get(i),"");
141 String calcModInvId = modVtx.<String>property("model-invariant-id").orElse(null);
142 // Now we can look up instances that match this model's info
143 Iterator<Vertex> tmpStartIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),calcModInvId).has(addDBAliasedSuffix("model-version-id"),calcModVerId);
144 while( tmpStartIter.hasNext() ){
145 Vertex tmpStartVert = (Vertex) tmpStartIter.next();
146 startVtxList.add(tmpStartVert);
150 if( !startVtxList.isEmpty() ){
151 startVerts = startVtxList.iterator();
156 if( startVerts != null ){
157 while( startVerts.hasNext() ){
158 Vertex tmpStartVert = (Vertex) startVerts.next();
159 String vid = tmpStartVert.id().toString();
160 String tmpModId = tmpStartVert.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null);
161 String tmpModVerId = tmpStartVert.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null);
162 startVertInfo.put(vid, tmpModVerId);
165 if( startVertInfo.isEmpty() ){
166 throw new AAIException("AAI_6114", "Start Node(s) could not be found for model data passed. " +
167 "(modelVersionId = [" + passedModelVersionId +
168 "], modelInvariantId = [" + passedModelInvId +
169 "], modelName = [" + passedModelName +
173 return startVertInfo;
176 // Use start-node filter info to find start-node(s) - Note - there could also be model info passed that we'll need
177 // to use to trim down the set of start-nodes that we find based on the startNodeFilter data.
178 String modTopNodeType ="";
179 String modInfoStr = "";
180 if( passedModelVersionId != null && !passedModelVersionId.equals("") ){
181 modTopNodeType = getModelVerTopWidgetType( transId, fromAppId, passedModelVersionId, "", "" );
182 modInfoStr = "modelVersionId = (" + passedModelVersionId + ")";
184 else if( passedModelInvId != null && !passedModelInvId.equals("") ){
185 modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", passedModelInvId, "" );
186 modInfoStr = "modelId = (" + passedModelInvId + ")";
188 else if( passedModelName != null && !passedModelName.equals("") ){
189 modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", "", passedModelName );
190 modInfoStr = "modelName = (" + passedModelName + ")";
193 if( modTopNodeType.equals("") ){
194 if( (passedTopNodeType == null) || passedTopNodeType.equals("") ){
195 String msg = "Could not determine the top-node nodeType for this request. modelInfo: [" + modInfoStr + "]";
196 throw new AAIException("AAI_6118", msg);
199 // We couldn't find a top-model-type based on passed in model info, but they
200 // gave us a type to use -- so use it.
201 modTopNodeType = passedTopNodeType;
205 // we did get a topNode type based on model info - make sure it doesn't contradict
206 // the passsed-in one (if there is one)
207 if( passedTopNodeType != null && !passedTopNodeType.equals("")
208 && !passedTopNodeType.equals(modTopNodeType) ){
209 throw new AAIException("AAI_6120", "topNodeType passed in [" + passedTopNodeType
210 + "] does not match nodeType derived for model info passed in: ["
211 + modTopNodeType + "]");
215 List<String> modelVersionIds2Check = new ArrayList<>();
216 if( (passedModelName != null && !passedModelName.equals("")) ){
217 // They passed a modelName, so find all the model UUIDs (model-version-id's) that map to this
218 modelVersionIds2Check = getModelVerIdsUsingName(transId, fromAppId, passedModelName);
220 if( (passedModelVersionId != null && !passedModelVersionId.equals("")) ){
221 // They passed in a modelNameVersionId
222 if( modelVersionIds2Check.isEmpty() ){
223 // There was no modelName passed, so we can use the passed modelNameVersionId
224 modelVersionIds2Check.add(passedModelVersionId);
226 else if( modelVersionIds2Check.contains(passedModelVersionId) ){
227 // The passed in uuid does not conflict with what we got using the passed-in modelName.
228 // We'll just use the passed in uuid in this case.
229 // Hopefully they would not be passing strange combinations like this, but we'll try to deal with it.
230 modelVersionIds2Check = new ArrayList<>(); // Clear out what we had
231 modelVersionIds2Check.add(passedModelVersionId);
235 // We should now be OK with our topNodeType for this request, so we can look for the actual startNodes
236 for( int i=0; i < startNodeFilterArrayOfHashes.size(); i++ ){
237 // Locate the starting node which will be used to look which corresponds to this set of filter data
238 Vertex startVtx = null;
240 Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(modTopNodeType, startNodeFilterArrayOfHashes.get(i));
241 if (!result.isPresent()) {
242 throw new AAIException("AAI_6114", "No Node of type " + modTopNodeType + " found for properties");
244 startVtx = result.get();
246 catch( AAIException e ){
247 String msg = "Could not find startNode of type = [" + modTopNodeType + "], given these params: "
248 + startNodeFilterArrayOfHashes.get(i) + ". msg # from getUniqueNode() = " + e.getMessage();
249 throw new AAIException("AAI_6114", msg);
252 String vid = startVtx.id().toString();
253 String personaModInvId = startVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null);
254 String personaModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null);
256 // Either this start-node has persona info (which should not contradict any passed-in model info)
257 // or they should have passed in the model to use - so we'd just use that.
258 if( personaModVerId != null && !personaModVerId.equals("") ){
259 // There is persona data in this start-node. So make sure it doesn't contradict any "passed" stuff
260 if( modelVersionIds2Check.isEmpty()
261 && (passedModelInvId == null || passedModelInvId.equals("")) ){
262 // They didn't pass any model info, so use the persona one.
263 startVertInfo.put(vid, personaModVerId);
265 else if( modelVersionIds2Check.isEmpty()
266 && (passedModelInvId != null && !passedModelInvId.equals("")) ){
267 // They passed in just the modelId - so check it
268 if( passedModelInvId.equals(personaModInvId) ){
269 startVertInfo.put(vid, personaModVerId);
272 else if( !modelVersionIds2Check.isEmpty()
273 && (passedModelInvId == null || passedModelInvId.equals("")) ){
274 // They passed in just modelVersionId - so check
275 if( modelVersionIds2Check.contains(personaModVerId) ){
276 startVertInfo.put(vid, personaModVerId);
279 else if( !modelVersionIds2Check.isEmpty()
280 && (passedModelInvId != null && !passedModelInvId.equals("")) ){
281 // We have BOTH a modelVersionIds and a modelId to check
282 if( passedModelInvId.equals(personaModInvId)
283 && modelVersionIds2Check.contains(personaModVerId) ){
284 startVertInfo.put(vid, personaModVerId);
289 // This start node did not have persona info -- so we will use the passed in model info if they passed one
290 if( passedModelVersionId!= null && !passedModelVersionId.equals("") ){
291 // The model-version-id uniquely identifies a model-ver, so we can use it.
292 startVertInfo.put(vid, passedModelVersionId);
295 throw new AAIException("AAI_6118", "Found startNode but since it does not have persona data, the " +
296 " model-version-id is required. ");
302 return startVertInfo;
304 }//end of getStartNodesAndModVersionIds()
308 * Query by model. (really model-ver)
310 * @param transId the trans id
311 * @param fromAppId the from app id
312 * @param modelVersionId the model-version-id (unique id in model-ver)
313 * @param modelInvariantId the model-invariant-id (unique id in model)
314 * @param modelName the model name
315 * @param topNodeType - optional (needed if neither model-invariant-id nor model-version-id is passed)
316 * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
317 * @param apiVer the api ver
319 * @throws AAIException the AAI exception
321 public List<ResultSet> queryByModel(String transId, String fromAppId,
322 String modelVersionId,
323 String modelInvariantId,
326 List<Map<String,Object>> startNodeFilterArrayOfHashes,
328 throws AAIException {
330 final String transId_f = transId;
331 final String fromAppId_f = fromAppId;
332 final String modelVersionId_f = modelVersionId;
333 final String modelInvId_f = modelInvariantId;
334 final String modelName_f = modelName;
335 final String topNodeType_f = topNodeType;
336 final List<Map<String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
337 final String apiVer_f = apiVer;
339 // Find out what our time-limit should be
340 int timeLimitSec = 0;
341 String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
342 if( timeLimitString != null && !timeLimitString.equals("") ){
344 timeLimitSec = Integer.parseInt(timeLimitString);
346 catch ( Exception nfe ){
347 // Don't worry, we will leave the limit as zero - which tells us not to use it.
351 if( timeLimitSec <= 0 ){
352 // We will NOT be using a timer
353 return queryByModel_Timed( transId, fromAppId,
358 startNodeFilterArrayOfHashes,
362 List<ResultSet> resultList = new ArrayList<>();
363 TimeLimiter limiter = new SimpleTimeLimiter();
365 resultList = limiter.callWithTimeout(new Callable <List<ResultSet>>() {
366 public List<ResultSet> call() throws AAIException {
367 return queryByModel_Timed( transId_f, fromAppId_f,
372 startNodeFilterArrayOfHashes_f,
375 }, timeLimitSec, TimeUnit.SECONDS, true);
377 catch (AAIException ae) {
378 // Re-throw AAIException so we get can tell what happened internally
381 catch (UncheckedTimeoutException ute) {
382 throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
384 catch (Exception e) {
385 throw new AAIException("AAI_6128", "Unexpected exception in queryByModel(): " + e.getMessage() );
393 * Query by model (model-ver) timed.
395 * @param transId the trans id
396 * @param fromAppId the from app id
397 * @param modelVersionId the model-version-id (unique id in model-ver)
398 * @param modelInvariantId the model-invariant-id (unique id in model)
399 * @param modelName the model name
400 * @param topNodeType the top node type
401 * @param startNodeFilterArrayOfHashes the start node filter array of hashes
402 * @param apiVer the api ver
403 * @return the array list
404 * @throws AAIException the AAI exception
406 public List<ResultSet> queryByModel_Timed(String transId, String fromAppId,
407 String modelVersionId,
408 String modelInvariantId,
411 List<Map<String,Object>> startNodeFilterArrayOfHashesVal,
413 throws AAIException {
415 List<ResultSet> resultArray = new ArrayList<>();
417 // NOTE: this method can be used for different styles of queries:
418 // a) They could pass neither a modelVersionId or a modelInvariantId but just pass a set of data defining start-nodes.
419 // Note - with no model info, we need them to pass the startNodeType for us to be able to use the
420 // start-node-filter data. We would look at each start node and ensure that each has persona-model info.
421 // Then use whatever model corresponds to each instance to pull that instance's data.
422 // b) They could pass a modelInvariantId, but no modelVersionId and no startNode info. In this case, we
423 // Would look in the database for all nodes that have a model-invariant-id-local that matches what was
424 // passed, and then for each of those instances, pull the data based on the corresponding model.
425 // c) They could pass a model-version-id, but no startNode info. We'd make sure that if a
426 // model-invariant-id was also passed, that it does not conflict - but it really should be null if they
427 // are passing a full model-version-id. Like case -b-, we'd do a query for all nodes
428 // that have persona info that corresponds to the model-version-id passed and then
429 // collect data for each one.
430 // d) They could pass either modelVersionId or modelInvariantId AND startNodeFilter info. In this case we
431 // would look at the model info to figure out what the top-node-type is, then look at the
432 // top-node instances based on the startNodeFilter. We'd only collect data for each instance if
433 // it's persona model info matches what was passed in.
436 // Sorry to do this, but code that gets called with an empty hash as the first array element was causing errors
437 List<Map<String,Object>> startNodeFilterArrayOfHashes = new ArrayList <Map<String,Object>>();
438 if( !startNodeFilterArrayOfHashesVal.isEmpty() ){
439 Map<String,Object> tmpH = startNodeFilterArrayOfHashesVal.get(0);
440 if( !tmpH.isEmpty() ){
441 for( int i=0; i < startNodeFilterArrayOfHashesVal.size(); i++ ){
442 startNodeFilterArrayOfHashes.add( startNodeFilterArrayOfHashesVal.get(i) );
447 // ----------------------------------------------------------------------------------------------------------
448 // Get a Hash of all the start-nodes (top instance-data node for a model-ver where we will
449 // start collecting data) for startNode2ModelVerHash:
450 // key = vertex-id for the startNode,
451 // value = model-version-id for the corresponding model-ver
452 // ----------------------------------------------------------------------------------------------------------
453 Map<String, String> startNode2ModelVerHash = getStartNodesAndModVersionIds( transId, fromAppId,
454 modelVersionId, modelInvariantId, modelName, topNodeType,
455 startNodeFilterArrayOfHashes, apiVer );
457 //System.out.println("\nDEBUG -- Here's a dump of the startnodes/model-vers: " + startNode2ModelVerHash.toString());
459 // --------------------------------------------------------------------------------------------------------
460 // Figure out what-all models (model-ver nodes) we will be dealing with
461 // Note - Instances must all use the same type of start-node, but do not have to all use the same model-ver.
462 // --------------------------------------------------------------------------------------------------------
463 Map<String, Vertex> distinctModelVersHash = new HashMap<>();
464 // For distinctModelVersHash: key = modelVersionId, val= modelVerVertex
465 String startNodeType = "";
466 if( topNodeType != null && !topNodeType.equals("") ){
467 startNodeType = topNodeType;
470 List<String> skipModelVerIdList = new ArrayList<>();
471 List<String> skipStartVertVerIdList = new ArrayList<>();
472 Set <String> snKeySet = startNode2ModelVerHash.keySet();
473 Iterator<String> startNodeIterator = snKeySet.iterator();
474 while( startNodeIterator.hasNext() ){
475 String modVerIdKey = (String) startNodeIterator.next();
476 String modVerId = startNode2ModelVerHash.get(modVerIdKey);
477 if( !distinctModelVersHash.containsKey(modVerId) ){
478 // First time seeing this model-version-id
479 Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver",
480 "model-version-id", modVerId);
481 String tmpNodeType = "";
483 tmpNodeType = getModelVerTopWidgetType( modVerVtx, "" );
485 catch( AAIException ae ){
486 // There must be some old bad data in the db - we will skip over this model-ver since its
487 // model is not good anymore - but will log that this is happening.
488 skipModelVerIdList.add(modVerId);
489 skipStartVertVerIdList.add(modVerIdKey);
490 System.out.println(">>> WARNING - will not collect model data for this vertex since " +
491 "it uses an inconsistant model-ver model. Model-version-id = " + modVerId );
494 if( tmpNodeType != null && !tmpNodeType.equals("") ){
495 if( startNodeType.equals("") ){
496 startNodeType = tmpNodeType;
498 else if( !startNodeType.equals(tmpNodeType) ){
499 String msg = "Conflict between startNode types for models involved: [" + startNodeType
500 + "], [" + tmpNodeType + "]";
501 throw new AAIException("AAI_6125", msg);
503 distinctModelVersHash.put(modVerId, modVerVtx);
508 //System.out.println("\nDEBUG -- Here's a dump of the DISTINCT model-ver hash: " + distinctModelVersHash.toString() );
510 // ------------------------------------------------------------------------------------------------------
511 // Get the "valid-next-step" hash for each distinct model-ver
512 // While we're at it, get a mapping of model-invariant-id|model-version to model-version-id for
513 // the model-vers being used
514 // ------------------------------------------------------------------------------------------------------
515 Map<String, Multimap<String, String>> validNextStepHash = new HashMap<>();
516 // validNextStepHash: key = modelVerId, value = nextStepMap
517 Set <String> keySet = distinctModelVersHash.keySet();
518 Iterator<String> modelVerIterator = keySet.iterator();
519 while( modelVerIterator.hasNext() ){
520 String modVerKey = (String) modelVerIterator.next();
521 if( ! skipModelVerIdList.contains(modVerKey) ){
522 Vertex modelVerVtx = (Vertex)distinctModelVersHash.get(modVerKey);
523 Multimap<String, String> tmpTopoMap = genTopoMap4ModelVer( transId, fromAppId,
524 modelVerVtx, modVerKey);
525 validNextStepHash.put(modVerKey, tmpTopoMap);
529 // -------------------------------------------------------------------------------------------------
530 // Figure out what the "start-node" for each instance will be (plus the info we will use to
531 // represent that in our topology)
532 // -------------------------------------------------------------------------------------------------
533 List<String> failedPersonaCheckVids = new ArrayList<>();
534 Map<String, String> firstStepInfoHash = new HashMap<>();
535 // For firstStepInfoHash: key = startNodeVtxId, val=topNodeType plus personaData if applicable
536 // ie. the value is what we'd use as the "first-step" for this model.
537 if( !nodeTypeSupportsPersona( startNodeType) ){
538 // This node type doesn't have persona info, so we just use startNodeType for the first-step-info
539 snKeySet = startNode2ModelVerHash.keySet();
540 startNodeIterator = snKeySet.iterator();
541 while( startNodeIterator.hasNext() ){
542 String vtxKey = (String) startNodeIterator.next();
543 firstStepInfoHash.put(vtxKey,startNodeType);
547 // Need to check that this node's persona data is good and if it is - use it for the first step info
548 snKeySet = startNode2ModelVerHash.keySet();
549 startNodeIterator = snKeySet.iterator();
550 while( startNodeIterator.hasNext() ){
551 String vtxKey = (String) startNodeIterator.next();
552 Iterator<Vertex> vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(vtxKey);
553 Vertex tmpVtx = (Vertex)vtxIterator.next();
554 String thisVtxModelVerId = startNode2ModelVerHash.get(vtxKey);
555 if( skipModelVerIdList.contains(thisVtxModelVerId) ){
556 // Skip this vertex because it uses a model-ver that is bad
559 Vertex modelVerVtx = (Vertex)distinctModelVersHash.get(thisVtxModelVerId);
560 Vertex modelVtx = getModelGivenModelVer( modelVerVtx, "" );
561 String modInvId = modelVtx.<String>property("model-invariant-id").orElse(null);
562 String personaModInvId = tmpVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null);
563 String personaModVerId = tmpVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null);
564 if( modInvId.equals(personaModInvId) && thisVtxModelVerId.equals(personaModVerId) ){
565 String tmpPersonaInfoStr = startNodeType + "," + personaModInvId + "," + personaModVerId;
566 firstStepInfoHash.put(vtxKey, tmpPersonaInfoStr );
569 // we won't use this start node below when we collect data because it should have
570 // had persona data that matched it's model - but it did not.
571 failedPersonaCheckVids.add(vtxKey);
576 //System.out.println("\nDEBUG -- Here's a dump of the firstStepInfoHash hash: " + firstStepInfoHash.toString() );
578 // ------------------------------------------------------------------------------------------------
579 // Loop through each start-node, collect it's data using collectInstanceData() and put the
580 // resultSet onto the resultArray.
581 // ------------------------------------------------------------------------------------------------
583 // Make sure they're not bringing back too much data
584 String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
585 if( maxString != null && !maxString.equals("") ){
588 maxSets = Integer.parseInt(maxString);
590 catch ( Exception nfe ){
591 // Don't worry, we will leave the max as zero - which tells us not to use it.
594 if( maxSets > 0 && (startNode2ModelVerHash.size() > maxSets) ){
595 String msg = " Query returns " + startNode2ModelVerHash.size() + " resultSets. Max allowed is: " + maxSets;
596 throw new AAIException("AAI_6141", msg);
600 snKeySet = startNode2ModelVerHash.keySet();
601 startNodeIterator = snKeySet.iterator();
602 while( startNodeIterator.hasNext() ){
603 String topNodeVtxId = (String) startNodeIterator.next();
604 if( failedPersonaCheckVids.contains(topNodeVtxId) ){
605 // Skip this vertex because it failed it's persona-data check above
608 if( skipStartVertVerIdList.contains(topNodeVtxId) ){
609 // Skip this vertex because it uses a model-ver that is bad
613 Iterator<Vertex> vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(topNodeVtxId);
614 Vertex tmpStartVtx = (Vertex)vtxIterator.next();
615 String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId);
616 String modelVerId = startNode2ModelVerHash.get(topNodeVtxId);
617 Multimap<String, String> validNextStepMap = validNextStepHash.get(modelVerId);
619 List<String> vidsTraversed = new ArrayList<>();
620 Map<String,String> emptyDelKeyHash = new HashMap<>();
621 Map<String,String> emptyNQElementHash = new HashMap<>(); // Only applies to Named Queries
622 ResultSet tmpResSet = collectInstanceData( transId, fromAppId,
623 tmpStartVtx, elementLocationTrail,
624 validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, emptyNQElementHash, apiVer );
626 resultArray.add(tmpResSet);
631 }// queryByModel_Timed()
636 * Run delete by model-ver.
638 * @param transId the trans id
639 * @param fromAppId the from app id
640 * @param modelVersionId the model version id -- unique id for a model-ver node
641 * @param topNodeTypeVal the top node type val -- required if no model-version-id is passed
642 * @param startNodeFilterHash the start node filter hash -- used to locate the first node of instance data
643 * @param apiVer the api ver
644 * @param resVersion the res version -- resourceVersion of the top/first widget in the model instance
645 * @return HashMap (keys = vertexIds that were deleted)
646 * @throws AAIException the AAI exception
648 public Map<String,String> runDeleteByModel( String transId, String fromAppId,
649 String modelVersionId, String topNodeTypeVal, Map<String,Object> startNodeFilterHash, String apiVer, String resVersion )
650 throws AAIException {
652 Map<String,String> retHash = new HashMap<>();
654 // Locate the Model-ver node to be used
655 Vertex modelVerVtx = null;
656 if( modelVersionId != null && !modelVersionId.equals("") ){
657 modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver",
658 "model-version-id", modelVersionId);
661 // if they didn't pass the modelVersionId, then we need to use the startNode to figure it out
662 // Locate the starting node based on the start node params
663 if( topNodeTypeVal == null || topNodeTypeVal.equals("") ){
664 throw new AAIException("AAI_6118", "If no model info is passed, then topNodeType is required. ");
667 Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(topNodeTypeVal, startNodeFilterHash);
668 if (!result.isPresent()) {
669 throw new AAIException("AAI_6114", "No Node of type " + topNodeTypeVal + " found for properties");
671 Vertex startVtx = result.get();
673 String startVertModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null);
674 modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver",
675 "model-version-id", startVertModVerId);
678 if( modelVerVtx == null ){
679 throw new AAIException("AAI_6114", "Could not determine the model-ver for the given input parameters. ");
682 String topNType = "unknown";
683 String modelType = getModelTypeFromModelVer( modelVerVtx, "" );
685 if( modelType.equals("widget") ){
686 // If they want to delete using a widget-level model.. That is just a delete of the one
687 // instance of one of our nodes.
688 String widgModNodeType = modelVerVtx.<String>property("model-name").orElse(null);
689 if( (widgModNodeType == null) || widgModNodeType.equals("") ){
690 String msg = "Could not find model-name for the widget model [" + modelVersionId + "].";
691 throw new AAIException("AAI_6132", msg);
693 Optional<Vertex> result = dbMethHelper.locateUniqueVertex(widgModNodeType, startNodeFilterHash);
694 if (!result.isPresent()) {
695 throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties");
697 Vertex widgetVtx = result.get();
698 String widgId = widgetVtx.id().toString();
699 serializer.delete(widgetVtx, resVersion, true);
700 retHash.put(widgId, widgModNodeType);
704 // ---------------------------------------------------------------------------------
705 // If we got to here, this must be either a service or resource model.
706 // So, we'll need to get a Hash of which parts of the model to delete.
707 // NOTE- deleteByModel is deleting data based on one specific version of a model.
708 // ---------------------------------------------------------------------------------
709 String chkFirstNodePersonaModInvId = "";
710 String chkFirstNodePersonaModVerId = "";
711 String personaData = "";
712 Vertex firstModElementVertex = getTopElementForSvcOrResModelVer( modelVerVtx, "" );
713 topNType = getModElementWidgetType( firstModElementVertex, "" );
714 if( (topNType == null) || topNType.equals("") ){
715 String msg = "Could not determine the top-node nodeType for model-version-id: [" + modelVersionId + "]";
716 throw new AAIException("AAI_6132", msg);
718 if( nodeTypeSupportsPersona(topNType) ){
719 Vertex modelVtx = getModelGivenModelVer(modelVerVtx,"");
720 chkFirstNodePersonaModInvId = modelVtx.<String>property("model-invariant-id").orElse(null);
721 chkFirstNodePersonaModVerId = modelVerVtx.<String>property("model-version-id").orElse(null);
722 personaData = "," + chkFirstNodePersonaModInvId + "," + chkFirstNodePersonaModVerId;
725 // Get the deleteKeyHash for this model
726 String incomingTrail = "";
727 Map<String, String> currentHash = new HashMap<>();
728 Map<String, Vertex> modConHash = new HashMap<>();
729 ArrayList <String> vidsTraversed = new ArrayList<>();
730 Map<String, String> delKeyHash = collectDeleteKeyHash( transId, fromAppId,
731 firstModElementVertex, incomingTrail, currentHash, vidsTraversed,
733 chkFirstNodePersonaModInvId, chkFirstNodePersonaModVerId );
736 System.out.println("\n ----DEBUG -----: Delete Hash for model: [" + modelVersionId + "] looks like: ");
737 for( Map.Entry<String, String> entry : delKeyHash.entrySet() ){
738 System.out.println("key = [" + entry.getKey() + "], val = [" + entry.getValue() + "]");
740 System.out.println("\n -----");
741 // Locate the starting node that we'll use to start looking for instance data
742 Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterHash);
743 if (!result.isPresent()) {
744 throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties");
746 Vertex startVtx = result.get();
747 if( !chkFirstNodePersonaModInvId.equals("") ){
748 // NOTE: For Service or Resource models, if this is a nodeType that supports persona's, then
749 // we need to make sure that the start node matches the persona values.
750 String startVertPersonaModInvId = startVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null);
751 String startVertPersonaModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null);
752 if( !chkFirstNodePersonaModInvId.equals(startVertPersonaModInvId)
753 || !chkFirstNodePersonaModVerId.equals(startVertPersonaModVerId) ){
754 String msg = "Persona-Model data mismatch for start node (" + topNType + "), " +
755 startNodeFilterHash ;
756 throw new AAIException("AAI_6114", msg);
759 String topVid = startVtx.id().toString();
761 // Read the model-ver into a Map for processing
762 Multimap<String, String> validNextStepMap = genTopoMap4ModelVer(transId, fromAppId,
763 modelVerVtx, modelVersionId);
766 String elementLocationTrail = topNType + personaData;
767 vidsTraversed = new ArrayList<>();
768 Map<String,String> emptyHash = new HashMap<>();
770 // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries
771 ResultSet retResSet = collectInstanceData( transId, fromAppId,
772 startVtx, elementLocationTrail,
773 validNextStepMap, vidsTraversed, 0, delKeyHash, emptyHash, apiVer );
775 // Note: the new ResultSet will have each element tagged with the del flag so we'll know if it
776 // should be deleted or not - so loop through the results in a try-block since some things
777 // will get auto-deleted by parents before we get to them --- and try to remove each one.
778 String vidToResCheck = topVid;
780 retHash = deleteAsNeededFromResultSet( transId, fromAppId, retResSet,
781 vidToResCheck, apiVer, resVersion, emptyHash );
782 //String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + ").";
786 }// End of runDeleteByModel()
791 * Delete as needed from result set.
793 * @param transId the trans id
794 * @param fromAppId the from app id
795 * @param resSet the res set
796 * @param vidToResCheck -- this vertex will need to have its resource-version checked
797 * @param apiVer the api ver
798 * @param resVersion the res version
799 * @param hashSoFar the hash so far -- hash of what's been deleted so far
801 * @throws AAIException the AAI exception
803 public Map<String,String> deleteAsNeededFromResultSet(String transId, String fromAppId,
804 ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, Map<String,String> hashSoFar )
807 Map<String,String> retHash = new HashMap<>();
808 retHash.putAll( hashSoFar );
809 Boolean deleteIt = false;
811 if( resSet.getVert() == null ){
815 Vertex thisVtx = resSet.getVert();
816 String thisGuyId = "";
818 String thisGuyStr = "";
820 Boolean gotVtxOK = false;
822 if( thisVtx != null ){
823 thisGuyId = thisVtx.id().toString();
824 thisNT = thisVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
825 thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + resSet.getLocationInModelSubGraph() + "]";
827 // NOTE -- will try to set the NodeType to itself to see if the node has been deleted already in
828 // this transaction. It lets you get properties from nodes being deleted where the
829 // delete hasn't been committed yet. This check used to be accomplished with a call to
830 // "vtx.isRemoved()" but that was a Titan-only feature and is not available anymore since
831 // we no longer use Titan vertices.
832 // If we don't do this check, we get errors later when we try to delete the node.
833 thisVtx.property(AAIProperties.NODE_TYPE, thisNT);
837 catch (Exception ex) {
838 // Sometimes things have already been deleted by the time we get to them - just log it.
839 LOGGER.warn("Exception when trying to delete: " + thisGuyStr + ". msg = " + ex.getMessage(), ex);
843 // The vertex must have already been removed. Just return.
844 // Note - We need to catch this because the DB sometimes can still have the vtx
845 // and be able to get its ID but it is flagged internally as removed already.
849 if( resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T") ){
850 LOGGER.info(">> will try to delete this one >> " + thisGuyStr);
853 Boolean requireResourceVersion = false;
854 if( thisGuyId.equals(vidToResCheck) ){
855 // This is the one vertex that we want to check the resourceId before deleting
856 requireResourceVersion = true;
858 this.serializer.delete(thisVtx, resVersion, requireResourceVersion);
860 catch (AAIException ae) {
861 String errorCode = ae.getErrorObject().getErrorCode();
862 if ( errorCode.equals("6130") || errorCode.equals("6131") ) {
863 // They didn't pass the correct resource-version for the top node.
867 String errText = ae.getErrorObject().getErrorText();
868 String errDetail = ae.getMessage();
869 LOGGER.warn("Exception when deleting " + thisGuyStr + ". ErrorCode = " + errorCode +
870 ", errorText = " + errText + ", details = " + errDetail);
873 catch( Exception e ){
874 // We'd expect to get a "node not found" here sometimes depending on the order that
875 // the model has us finding / deleting nodes.
876 // Ignore the exception - but log it so we can see what happened.
877 LOGGER.warn("Exception when deleting " + thisGuyStr + e.getMessage(), e);
880 // We can't depend on a thrown exception to tell us if a node was deleted since it may
881 // have been auto=deleted before this removeAaiNode() call.
882 // --- Not sure if we would want to check anything here -- because the graph.commit() is done outside of this call.
888 System.out.println(">>>>>>> NOT DELETING THIS ONE >>>> " + thisGuyStr );
889 List<String> retArr = dbMethHelper.getVertexProperties(thisVtx);
890 for( String info : retArr ){ System.out.println(info); }
895 // Now call this routine for the sub-resultSets
896 List <ResultSet> subResultSetList = resSet.getSubResultSet();
897 Iterator <ResultSet> subResSetIter = subResultSetList.iterator();
898 while( subResSetIter.hasNext() ){
899 ResultSet tmpSubResSet = subResSetIter.next();
900 retHash = deleteAsNeededFromResultSet( transId, fromAppId, tmpSubResSet,
901 vidToResCheck, apiVer, resVersion, retHash );
905 retHash.put(thisGuyId, thisGuyStr);
910 }// deleteAsNeededFromResultSet()
915 * Query by named query (old version).
917 * @param transId the trans id
918 * @param fromAppId the from app id
919 * @param namedQueryUuid the named query uuid
920 * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
921 * @param apiVer the api ver
923 * @throws AAIException the AAI exception
925 public List<ResultSet> queryByNamedQuery(String transId, String fromAppId,
926 String namedQueryUuid,
927 ArrayList <Map<String,Object>> startNodeFilterArrayOfHashes,
929 throws AAIException {
931 String dummyCutPoint = null;
932 Map<String,Object> dummySecondaryFilterHash = null;
934 return queryByNamedQuery( transId, fromAppId,
936 startNodeFilterArrayOfHashes,
939 dummySecondaryFilterHash );
944 * Query by named query.
946 * @param transId the trans id
947 * @param fromAppId the from app id
948 * @param namedQueryUuid the named query uuid
949 * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
950 * @param apiVer the api ver
951 * @param secondaryCutPoint nodeType where we will prune if secondary filter is not met
952 * @param secondaryFilterHash secondary filter params
954 * @throws AAIException the AAI exception
956 public List<ResultSet> queryByNamedQuery(String transId, String fromAppId,
957 String namedQueryUuid,
958 List<Map<String,Object>> startNodeFilterArrayOfHashes,
960 String secondaryFilterCutPoint,
961 Map<String,Object> secondaryFilterHash )
962 throws AAIException {
964 final String transId_f = transId;
965 final String fromAppId_f = fromAppId;
966 final String namedQueryUuid_f = namedQueryUuid;
967 final List<Map<String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
968 final String apiVer_f = apiVer;
969 final String secondaryFilterCutPoint_f = secondaryFilterCutPoint;
970 final Map<String,Object> secondaryFilterHash_f = secondaryFilterHash;
972 // Find out what our time-limit should be
973 int timeLimitSec = 0;
974 String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
975 if( timeLimitString != null && !timeLimitString.equals("") ){
977 timeLimitSec = Integer.parseInt(timeLimitString);
979 catch ( Exception nfe ){
980 // Don't worry, we will leave the limit as zero - which tells us not to use it.
984 if( timeLimitSec <= 0 ){
985 // We will NOT be using a timer
986 return queryByNamedQuery_Timed( transId, fromAppId,
988 startNodeFilterArrayOfHashes,
990 secondaryFilterCutPoint_f,
991 secondaryFilterHash_f );
994 List<ResultSet> resultList = new ArrayList<>();
995 TimeLimiter limiter = new SimpleTimeLimiter();
997 resultList = limiter.callWithTimeout(new Callable <List<ResultSet>>() {
998 public List<ResultSet> call() throws AAIException {
999 return queryByNamedQuery_Timed( transId_f, fromAppId_f,
1001 startNodeFilterArrayOfHashes_f,
1003 secondaryFilterCutPoint_f,
1004 secondaryFilterHash_f );
1006 }, timeLimitSec, TimeUnit.SECONDS, true);
1009 catch (AAIException ae) {
1010 // Re-throw AAIException so we get can tell what happened internally
1013 catch (UncheckedTimeoutException ute) {
1014 throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
1016 catch (Exception e) {
1017 throw new AAIException("AAI_6128", "Unexpected exception in queryByNamedQuery(): " + e.getMessage() );
1025 * Query by named query timed.
1027 * @param transId the trans id
1028 * @param fromAppId the from app id
1029 * @param namedQueryUuid the named query uuid
1030 * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
1031 * @param apiVer the api ver
1032 * @param secondaryFilterCutPoint the nodeType where we will parse for the secondary Filter
1033 * @param secondaryFilterHash the secondary filter hash
1035 * @throws AAIException the AAI exception
1037 public List<ResultSet> queryByNamedQuery_Timed(String transId, String fromAppId,
1038 String namedQueryUuid,
1039 List<Map<String,Object>> startNodeFilterArrayOfHashes,
1041 String secondaryFilterCutPoint,
1042 Map<String,Object> secondaryFilterHash
1044 throws AAIException {
1046 // Locate the Query to be used
1047 Vertex queryVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query",
1048 "named-query-uuid", namedQueryUuid);
1050 // Get the first/top named-query-element used by this query
1051 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVtx, "named-query-element");
1052 Vertex firstNqElementVert = null;
1054 String topNType = "";
1055 while( vertI != null && vertI.hasNext() ){
1056 firstNqElementVert = vertI.next();
1058 topNType = getNqElementWidgetType( transId, fromAppId, firstNqElementVert, "" );
1062 // A named query must start with a single top element
1063 throw new AAIException("AAI_6133", "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]");
1065 else if( count > 1 ){
1066 // A named query should start with a single top element
1067 throw new AAIException("AAI_6133", "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]");
1069 if( (topNType == null) || topNType.equals("") ){
1070 String msg = "Could not determine the top-node nodeType for Named Query: [" + namedQueryUuid + "]";
1071 throw new AAIException("AAI_6133", msg);
1074 // Read the topology into a hash for processing
1075 Multimap<String, String> validNextStepMap = genTopoMap4NamedQ(transId, fromAppId, queryVtx, namedQueryUuid);
1077 List<Vertex> startVertList = new ArrayList<>();
1078 if( startNodeFilterArrayOfHashes.size() == 1 ){
1079 // If there is only one set of startFilter info given, then allow it to possibly not be
1080 // defining just one start node.
1081 Map<String, Object> cleanHash = new HashMap<>();
1082 Map<String, Object> tmpHash = startNodeFilterArrayOfHashes.get(0);
1083 Set <String> propKeySet = tmpHash.keySet();
1084 Iterator<String> propIter = propKeySet.iterator();
1085 Introspector obj = loader.introspectorFromName(topNType);
1086 Set<String> keys = obj.getKeys();
1087 boolean foundIndexedField = false;
1088 int propertiesSet = 0;
1089 while( propIter.hasNext() ){
1090 String oldVtxKey = (String) propIter.next();
1091 String newKey = oldVtxKey;
1092 String [] parts = oldVtxKey.split("\\.");
1093 if( parts.length == 2 ){
1096 Object obVal = tmpHash.get(oldVtxKey);
1097 if (obj.hasProperty(newKey)) {
1098 if (keys.contains(newKey)) {
1099 foundIndexedField = true;
1101 obj.setValue(newKey, obVal);
1105 //we found all the properties in the startNodeType
1106 if (propertiesSet == propKeySet.size()) {
1107 if (foundIndexedField) {
1108 QueryBuilder builder = this.engine.getQueryBuilder().exactMatchQuery(obj);
1109 startVertList = builder.toList();
1111 //force a filter from aai-node-type
1112 QueryBuilder builder = this.engine.getQueryBuilder().createContainerQuery(obj).exactMatchQuery(obj);
1113 startVertList = builder.toList();
1116 Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(0));
1117 // Only found one, so just use it.
1118 if (tmpVtx.isPresent()) {
1119 startVertList.add(tmpVtx.get());
1124 // Since they give an array of startNodeFilterHash info, we expect each one
1125 // to just point to one node.
1126 for( int i = 0; i < startNodeFilterArrayOfHashes.size(); i++ ){
1127 // Locate the starting node for each set of data
1128 Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(i));
1129 if (tmpVtx.isPresent()) {
1130 startVertList.add(tmpVtx.get());
1135 if (startVertList.isEmpty()) {
1136 throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties");
1138 // Make sure they're not bringing back too much data
1139 String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
1140 if( maxString != null && !maxString.equals("") ){
1141 int maxSets = Integer.parseInt(maxString);
1142 if( startVertList.size() > maxSets ){
1143 String msg = " Query returns " + startVertList.size() + " resultSets. Max allowed is: " + maxSets;
1144 throw new AAIException("AAI_6141", msg);
1148 // Loop through each start node and get its data
1149 List<ResultSet> resSetList = new ArrayList<>();
1150 for( int i = 0; i < startVertList.size(); i++ ){
1151 Vertex startVtx = startVertList.get(i);
1153 String elementLocationTrail = topNType;
1154 ArrayList <String> vidsTraversed = new ArrayList<>();
1155 Map<String,String> emptyDelKeyHash = new HashMap<>(); // Does not apply to Named Queries
1157 // Get the mapping of namedQuery elements to our widget topology for this namedQuery
1158 String incomingTrail = "";
1159 Map<String, String> currentHash = new HashMap<>();
1161 Map<String,String> namedQueryElementHash = collectNQElementHash( transId, fromAppId,
1162 firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 );
1164 vidsTraversed = new ArrayList<>();
1165 ResultSet tmpResSet = collectInstanceData( transId, fromAppId,
1166 startVtx, elementLocationTrail,
1167 validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, namedQueryElementHash, apiVer );
1168 resSetList.add(tmpResSet);
1171 // If a secondary filter was defined, we will prune the collected instance data result set(s) based on it.
1172 List<ResultSet> prunedResSetList = new ArrayList<>();
1173 if( resSetList != null && !resSetList.isEmpty() ){
1174 for( int i = 0; i < resSetList.size(); i++ ){
1175 if( secondaryFilterCutPoint == null || secondaryFilterCutPoint.equals("") || secondaryFilterHash == null ){
1176 // They didn't want to do any pruning, so just use the results we already had
1177 prunedResSetList.add(resSetList.get(i));
1180 ResultSet tmpResSet = pruneResultSet(resSetList.get(i), secondaryFilterCutPoint, secondaryFilterHash);
1181 if( tmpResSet != null ){
1182 prunedResSetList.add(tmpResSet);
1188 // Since a NamedQuery can mark some nodes as "do-not-display", we need to collapse our resultSet so
1189 // does not display those nodes.
1190 List<ResultSet> collapsedResSetList = new ArrayList<>();
1191 if( prunedResSetList != null && !prunedResSetList.isEmpty() ){
1192 for( int i = 0; i < prunedResSetList.size(); i++ ){
1193 // Note - a single resultSet could be collapsed into many smaller ones if they
1194 // marked all the "top" node-elements as do-not-output. Ie. the query may
1195 // have had a top-node of "generic-vnf" which joins down to different l-interfaces.
1196 // If they only want to see the l-interfaces, then a single result set
1197 // would be "collapsed" into many separate resultSets - each of which is
1198 // just a single l-interface.
1199 List<ResultSet> tmpResSetList = collapseForDoNotOutput(prunedResSetList.get(i));
1200 if( tmpResSetList != null && !tmpResSetList.isEmpty() ){
1201 for( int x = 0; x < tmpResSetList.size(); x++ ){
1202 //showResultSet( tmpResSetList.get(x), 0 ); //DEBUG-- this was just for testing
1203 collapsedResSetList.add(tmpResSetList.get(x));
1209 return collapsedResSetList;
1211 }// End of queryByNamedQuery()
1215 * Prune a result set as per a secondary filter.
1217 * @param resSetVal the res set val
1218 * @param cutPoint the nodeType where the trim will happen
1219 * @param secFilterHash hash of properties and values to use as the secondary filter
1220 * @return pruned result set
1221 * @throws AAIException the AAI exception
1223 public ResultSet pruneResultSet(ResultSet resSetVal, String cutPointType, Map<String,Object> secFilterHash )
1224 throws AAIException {
1226 // Given a ResultSet and some secondary filter info, do pruning as needed
1227 ResultSet pResSet = new ResultSet();
1229 // For this ResultSet, we will see if we are on a node of the type that is our cutPoint;
1230 // then only keep it if we peek "below" and see a match for our filter.
1232 String nt = resSetVal.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null);
1233 if( nt != null && nt.equals(cutPointType) ){
1234 // We are on the type of node that may need to be "pruned" along with it's sub-results
1235 if( ! satisfiesFilters(resSetVal, secFilterHash) ){
1236 // Return an empty result set since we are pruning at this level.
1241 // If we made it to here, we will not be pruning at this level, so we will
1242 // be returning a copy of this resultSet that has it's subResults pruned (as needed).
1243 pResSet.setVert(resSetVal.getVert());
1244 pResSet.setDoNotOutputFlag(resSetVal.getDoNotOutputFlag());
1245 pResSet.setExtraPropertyHash(resSetVal.getExtraPropertyHash());
1246 pResSet.setLocationInModelSubGraph(resSetVal.getLocationInModelSubGraph());
1247 pResSet.setNewDataDelFlag(resSetVal.getNewDataDelFlag());
1248 pResSet.setPropertyLimitDesc(resSetVal.getPropertyLimitDesc());
1249 pResSet.setPropertyOverRideHash(resSetVal.getPropertyOverRideHash());
1251 if( !resSetVal.getSubResultSet().isEmpty() ){
1252 ListIterator<ResultSet> listItr = resSetVal.getSubResultSet().listIterator();
1253 List<ResultSet> newSubSetList = new ArrayList<>();
1254 while( listItr.hasNext() ){
1255 ResultSet tmpSubResSet = pruneResultSet( listItr.next(), cutPointType, secFilterHash );
1256 if( tmpSubResSet.getVert() != null ){
1257 // This one wasn't pruned - so keep it.
1258 newSubSetList.add(tmpSubResSet);
1261 pResSet.setSubResultSet(newSubSetList);
1266 }// End pruneResultSet()
1270 * Satisfies hash of filters.
1272 * @param resSet the res set
1273 * @param filterHash the filter hash
1274 * @return true, if successful
1275 * @throws AAIException the AAI exception
1277 public boolean satisfiesFilters(ResultSet resSet, Map<String,Object> filterHash )
1278 throws AAIException {
1280 if( filterHash.isEmpty() ){
1281 // Nothing to look for, so no, we didn't find it.
1285 Iterator <?> it = filterHash.entrySet().iterator();
1286 while( it.hasNext() ){
1287 Map.Entry<?,?> filtEntry = (Map.Entry<?,?>) it.next();
1288 String propNodeTypeDotName = (filtEntry.getKey()).toString();
1289 String fpv = (filtEntry.getValue()).toString();
1291 int periodLoc = propNodeTypeDotName.indexOf(".");
1292 if( periodLoc <= 0 ){
1293 String emsg = "Bad filter param key passed in: [" + propNodeTypeDotName + "]. Expected format = [nodeName.paramName]\n";
1294 throw new AAIException("AAI_6120", emsg);
1297 String fnt = propNodeTypeDotName.substring(0,periodLoc);
1298 String fpn = propNodeTypeDotName.substring(periodLoc + 1);
1299 if( filterMetByThisSet( resSet, fnt, fpn, fpv ) ){
1300 //System.out.println(" DEBUG -- satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "].");
1303 //System.out.println(" DEBUG -- NOT satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "].");
1309 // Made it through all the filters -- it found what we were looking for.
1312 }// end of satisfiesFilters()
1316 * Filter met by this set.
1318 * @param resSet the res set
1319 * @param filtNodeType the filt node type
1320 * @param filtPropName the filt prop name
1321 * @param filtPropVal the filt prop val
1322 * @return true, if successful
1324 public boolean filterMetByThisSet(ResultSet resSet, String filtNodeType, String filtPropName, String filtPropVal ) {
1325 // Note - we are just looking for a positive match for one filter for this resultSet
1326 // NOTE: we're expecting the filter to have a format like this: "nodeType.parameterName:parameterValue"
1328 Vertex vert = resSet.getVert();
1333 String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null);
1334 if( nt.equals( filtNodeType ) ){
1335 if( filtPropName.equals("vertex-id") ){
1336 // vertex-id can't be gotten the same way as other properties
1337 String thisVtxId = vert.id().toString();
1338 if( thisVtxId.equals(filtPropVal) ){
1343 Object thisValObj = vert.property(filtPropName).orElse(null);
1344 if( thisValObj != null ){
1345 String thisVal = thisValObj.toString();
1346 if( thisVal.equals(filtPropVal) ){
1354 // Didn't find a match at the this level, so check the sets below it meet the criteria
1355 if( resSet.getSubResultSet() != null ){
1356 ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator();
1357 while( listItr.hasNext() ){
1358 if( filterMetByThisSet(listItr.next(), filtNodeType, filtPropName, filtPropVal) ){
1366 }// end of filterMetByThisSet()
1371 * Collapse for do not output.
1373 * @param resSetVal the res set val
1374 * @return the array list
1375 * @throws AAIException the AAI exception
1377 public List<ResultSet> collapseForDoNotOutput(ResultSet resSetVal )
1378 throws AAIException {
1380 // Given a ResultSet -- if it is tagged to NOT be output, then replace it with
1381 // it's sub-ResultSets if it has any.
1382 List<ResultSet> colResultSet = new ArrayList<>();
1384 if( resSetVal.getDoNotOutputFlag().equals("true") ){
1385 // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets
1386 List<ResultSet> subResList = (ArrayList<ResultSet>) resSetVal.getSubResultSet();
1387 for( int k = 0; k < subResList.size(); k++ ){
1388 List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(k));
1389 colResultSet.addAll(newSubResList);
1393 // This set will be displayed
1394 colResultSet.add(resSetVal);
1397 // For each result set now at this level, call this same routine to collapse their sub-resultSets
1398 for( int i = 0; i < colResultSet.size(); i++ ){
1399 List<ResultSet> newSubSet = new ArrayList<>();
1400 List<ResultSet> subResList = (ArrayList<ResultSet>) colResultSet.get(i).getSubResultSet();
1401 for( int n = 0; n < subResList.size(); n++ ){
1402 List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(n));
1403 newSubSet.addAll(newSubResList);
1405 // Replace the old subResultSet with the collapsed set
1406 colResultSet.get(i).setSubResultSet(newSubSet);
1409 return colResultSet;
1411 }// End collapseForDoNotOutput()
1416 * Collect instance data.
1418 * @param transId the trans id
1419 * @param fromAppId the from app id
1420 * @param thisLevelElemVtx the element vtx at this level
1421 * @param thisVertsTrail the this verts trail
1422 * @param elementLocationTrail -- trail of nodeTypes that got us here (this element vertex) from the top
1423 * @param validNextStepMap the valid next step map -- hash of valid next steps (node types) for this model
1424 * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
1425 * @param levelCounter the level counter
1426 * @param delKeyHash -- hashMap of which spots on our topology should be deleted during a modelDelete
1427 * @param namedQueryElementHash - hashMap which maps each spot in our widget topology to the NamedQueryElemment that it maps to
1428 * @param apiVer the api ver
1430 * @throws AAIException the AAI exception
1432 public ResultSet collectInstanceData(String transId, String fromAppId,
1433 Vertex thisLevelElemVtx,
1434 String thisVertsTrail,
1435 Multimap<String,String> validNextStepMap,
1436 List<String> vidsTraversed,
1438 Map<String,String> delKeyHash, // only applies when collecting data using the default model for delete
1439 Map<String,String> namedQueryElementHash, // only applies to named-query data collecting
1441 ) throws AAIException {
1445 String thisElemVid = thisLevelElemVtx.id().toString();
1447 if( levelCounter > MAX_LEVELS ) {
1448 throw new AAIException("AAI_6125", "collectInstanceData() has looped across more levels than allowed: " + MAX_LEVELS + ". ");
1451 ResultSet rs = new ResultSet();
1452 if( namedQueryElementHash.containsKey(thisVertsTrail) ){
1453 // We're collecting data for a named-query, so need to see if we need to do anything special
1454 String nqElUuid = namedQueryElementHash.get(thisVertsTrail);
1455 Vertex nqElementVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query-element",
1456 "named-query-element-uuid", nqElUuid);
1458 String tmpDoNotShow = nqElementVtx.<String>property("do-not-output").orElse(null);
1459 if( tmpDoNotShow != null && tmpDoNotShow.equals("true") ){
1460 rs.setDoNotOutputFlag("true");
1463 if( namedQueryConstraintSaysStop(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer) ){
1464 // There was a property constraint which says they do not want to collect this vertex or whatever
1465 // might be below it. Just return the empty rs here.
1469 String propLimDesc = nqElementVtx.<String>property("property-limit-desc").orElse(null);
1470 if( (propLimDesc != null) && !propLimDesc.equals("") ){
1471 if (propLimDesc.equalsIgnoreCase("show-all")) {
1472 rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_ALL);
1473 } else if (propLimDesc.equalsIgnoreCase("show-none")) {
1474 rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NONE);
1475 }else if (propLimDesc.equalsIgnoreCase("name-and-keys-only")) {
1476 rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY);
1480 // Look to see if we need to use an Override of the normal properties
1481 Map<String,Object> tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer);
1482 //System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + tmpPropertyOverRideHash.toString() + "]");
1483 rs.setPropertyOverRideHash(tmpPropertyOverRideHash);
1485 // See if we need to look up any "unconnected" data that needs to be associated with this result set
1486 Map<String,Object> tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer);
1487 //System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + tmpExtraPropHash.toString() + "]");
1488 rs.setExtraPropertyHash(tmpExtraPropHash);
1491 rs.setVert(thisLevelElemVtx);
1492 rs.setLocationInModelSubGraph(thisVertsTrail);
1493 if( delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T") ){
1494 rs.setNewDataDelFlag("T");
1497 rs.setNewDataDelFlag("F");
1500 // Use Gremlin-pipeline to just look for edges that go to a valid "next-steps"
1501 Collection <String> validNextStepColl = validNextStepMap.get(thisVertsTrail);
1503 // Because of how we process linkage-points, we may have duplicate node-types in our next-stepMap (for one step)
1504 // So, to keep from looking (and bringing back) the same data twice, we need to make sure our next-steps are unique
1505 Set<String> validNextStepHashSet = new HashSet<>();
1506 Iterator <String> ntcItr = validNextStepColl.iterator();
1507 while( ntcItr.hasNext() ){
1508 String targetStepStr = ntcItr.next();
1509 validNextStepHashSet.add(targetStepStr);
1512 List<String> tmpVidsTraversedList = new ArrayList<>();
1513 tmpVidsTraversedList.addAll(vidsTraversed);
1514 tmpVidsTraversedList.add(thisElemVid);
1516 Iterator <String> ntItr = validNextStepHashSet.iterator();
1517 while( ntItr.hasNext() ){
1518 String targetStep = ntItr.next();
1519 // NOTE: NextSteps can either be just a nodeType, or can be a nodeType plus
1520 // model-invariant-id-local and model-version-id-local (the two persona properties)
1521 // if those need to be checked also.
1522 // When the persona stuff is part of the step, it is a comma separated string.
1523 // Ie. "nodeType,model-inv-id-local,model-version-id-local" (the two "persona" props)
1525 String targetNodeType = "";
1528 Boolean stepIsJustNT = true;
1529 if( targetStep.contains(",") ){
1530 stepIsJustNT = false;
1531 String[] pieces = targetStep.split(",");
1532 if( pieces.length != 3 ){
1533 throw new AAIException("AAI_6128", "Unexpected format for nextStep in model processing = ["
1534 + targetStep + "]. ");
1537 targetNodeType = pieces[0];
1543 // It's just the nodeType with no other info
1544 targetNodeType = targetStep;
1547 GraphTraversal<Vertex, Vertex> modPipe = null;
1549 modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType);
1552 modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType).has(addDBAliasedSuffix("model-invariant-id"),pmid).has(addDBAliasedSuffix("model-version-id"),pmv);
1555 if( modPipe == null || !modPipe.hasNext() ){
1556 //System.out.println("DEBUG - didn't find any [" + targetStep + "] connected to this guy (which is ok)");
1559 while( modPipe.hasNext() ){
1560 Vertex tmpVert = (Vertex) modPipe.next();
1561 String tmpVid = tmpVert.id().toString();
1562 String tmpTrail = thisVertsTrail + "|" + targetStep;
1563 if( !vidsTraversed.contains(tmpVid) ){
1564 // This is one we would like to use - so we'll include the result set we get for it
1565 ResultSet tmpResSet = collectInstanceData( transId, fromAppId,
1567 validNextStepMap, tmpVidsTraversedList,
1568 levelCounter, delKeyHash, namedQueryElementHash, apiVer );
1570 rs.getSubResultSet().add(tmpResSet);
1578 } // End of collectInstanceData()
1582 * Gen topo map 4 model.
1584 * @param transId the trans id
1585 * @param fromAppId the from app id
1586 * @param modelVerVertex the model-ver vertex
1587 * @param modelVerId the model-version-id
1588 * @param loader the db maps
1589 * @return MultiMap of valid next steps for each potential model-element
1590 * @throws AAIException the AAI exception
1592 public Multimap<String, String> genTopoMap4ModelVer(String transId, String fromAppId,
1593 Vertex modelVerVertex, String modelVerId)
1594 throws AAIException {
1596 if( modelVerVertex == null ){
1597 throw new AAIException("AAI_6114", "null modelVerVertex passed to genTopoMap4ModelVer()");
1600 Multimap<String, String> initialEmptyMap = ArrayListMultimap.create();
1601 List<String> vidsTraversed = new ArrayList<>();
1602 String modelType = getModelTypeFromModelVer( modelVerVertex, "" );
1603 if( modelType.equals("widget") ){
1604 // A widget model by itself does not have a topoplogy. That is - it has no "model-elements" which
1605 // define how it is connected to other things. All it has is a name which ties it to
1607 Iterator<Vertex> vertI= this.traverseIncidentEdges(EdgeType.TREE, modelVerVertex, "model-element");
1608 if( vertI != null && vertI.hasNext() ){
1609 throw new AAIException("AAI_6132", "Bad Model Definition: Widget Model has a startsWith edge to a model-element. "
1610 + " model-version-id = " + modelVerId);
1613 return initialEmptyMap;
1617 String firstModelVerId = modelVerVertex.<String>property("model-version-id").orElse(null);
1618 String firstModelVersion = modelVerVertex.<String>property("model-version").orElse(null);
1619 if( firstModelVerId == null || firstModelVerId.equals("") || firstModelVersion == null || firstModelVersion.equals("") ){
1620 throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-version-id or model-version. model-version-id = "
1624 Vertex firstElementVertex = getTopElementForSvcOrResModelVer( modelVerVertex, "" );
1625 Vertex firstEleModVerVtx = getModelVerThatElementRepresents( firstElementVertex, "" );
1626 String firstElemModelType = getModelTypeFromModelVer( firstEleModVerVtx, "" );
1627 if( ! firstElemModelType.equals("widget") ){
1628 throw new AAIException("AAI_6132", "Bad Model Definition: First element must correspond to a widget type model. Model UUID = "
1632 Vertex firstModVtx = getModelGivenModelVer( modelVerVertex, "" );
1633 String firstModelInvId = firstModVtx.<String>property("model-invariant-id").orElse(null);
1634 if( firstModelInvId == null || firstModelInvId.equals("") ){
1635 throw new AAIException("AAI_6132", "Bad Model Definition: Could not find model.model-invariant-id given model-ver.model-version-id = "
1639 Multimap<String, String> collectedMap = collectTopology4ModelVer( transId, fromAppId,
1640 firstElementVertex, "", initialEmptyMap, vidsTraversed, 0, null, firstModelInvId, firstModelVersion );
1642 return collectedMap;
1644 } // End of genTopoMap4ModelVer()
1647 public List<String> makeSureItsAnArrayList( String listStringVal ){
1648 // We're sometimes getting a String back on db properties that should be ArrayList<String>
1649 // Seems to be how they're defined in OXM - whether they use a "xml-wrapper" or not
1650 // Need to translate them into ArrayLists sometimes...
1652 List<String> retArrList = new ArrayList<String>();
1653 String listString = listStringVal;
1654 listString = listString.replace(" ", "");
1655 listString = listString.replace("\"", "");
1656 listString = listString.replace("[", "");
1657 listString = listString.replace("]", "");
1658 String [] pieces = listString.split(",");
1659 if( pieces != null && pieces.length > 0 ){
1660 for( int i = 0; i < pieces.length; i++ ){
1661 retArrList.add(pieces[i]);
1670 * Gets the mod constraint hash.
1672 * @param modelElementVtx the model element vtx
1673 * @param currentHash -- the current ModelConstraint's that this routine will add to if it finds any.
1674 * @return HashMap of model-constraints that will be looked at for this model-element and what's "below" it.
1675 * @throws AAIException the AAI exception
1677 public Map<String, Vertex> getModConstraintHash(Vertex modelElementVtx, Map<String, Vertex> currentHash )
1678 throws AAIException {
1680 // For a given model-element vertex, look to see if there are any "model-constraint" elements that is has
1681 // an OUT "uses" edge to. If it does, then get any "constrained-element-set" nodes that are pointed to
1682 // by the "model-constraint". That will be the replacement "constrained-element-set". The UUID of the
1683 // "constrained-element-set" that it is supposed to replace is found in the property:
1684 // model-constraint.constrained-element-set-uuid-to-replace
1686 // For now, that is the only type of model-constraint allowed, so that is all we will look for.
1687 // Pass back any of these "constrained-element-set" nodes along with any that were passed in by
1688 // the "currentHash" parameter.
1690 if( modelElementVtx == null ){
1691 String msg = " null modelElementVtx passed to getModConstraintHash() ";
1692 throw new AAIException("AAI_6114", msg);
1695 String modelType = modelElementVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
1696 if( modelType == null || (!modelType.equals("model-element")) ){
1697 String msg = " getModConstraintHash() called with wrong type model: [" + modelType + "]. ";
1698 throw new AAIException("AAI_6114", msg);
1701 Map<String, Vertex> thisHash = new HashMap<>();
1702 if( currentHash != null ){
1703 thisHash.putAll(currentHash);
1707 List<Vertex> modelConstraintArray = new ArrayList<>();
1708 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, modelElementVtx, "model-constraint");
1709 while( vertI != null && vertI.hasNext() ){
1710 Vertex tmpVert = vertI.next();
1711 String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null);
1712 if( (connectToType != null) && connectToType.equals("model-constraint") ){
1713 // We need to find the constrained element set pointed to by this and add it to the Hash to return
1714 modelConstraintArray.add(tmpVert);
1720 for( int i = 0; i < count; i++ ){
1721 Vertex vtxOfModelConstraint = modelConstraintArray.get(i);
1722 String uuidOfTheOneToBeReplaced = vtxOfModelConstraint.<String>property("constrained-element-set-uuid-2-replace").orElse(null);
1723 // We have the UUID of the constrained-element-set that will be superseded, now find the
1724 // constrained-element-set to use in its place
1725 Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, vtxOfModelConstraint, "constrained-element-set");
1726 while( mvertI != null && mvertI.hasNext() ){
1727 // There better only be one...
1728 Vertex tmpVert = mvertI.next();
1729 String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null);
1730 if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
1731 // This is the "constrained-element-set" that we want to use as the Replacement
1732 thisHash.put(uuidOfTheOneToBeReplaced, tmpVert );
1739 // Didn't find anything to add, so just return what they passed in.
1743 } // End of getModConstraintHash()
1747 * Gets the top element vertex for service or resource model.
1749 * @param modelVerVtx the model-ver vertex
1750 * @return first element pointed to by this model-ver
1751 * @throws AAIException the AAI exception
1753 public Vertex getTopElementForSvcOrResModelVer(Vertex modelVerVtx, String trail )
1754 throws AAIException {
1756 // For a "resource" or "service" type model, return the "top" element in that model
1757 if( modelVerVtx == null ){
1758 String msg = " null modelVertex passed to getTopoElementForSvcOrResModelVer() at [" + trail + "]. ";
1759 throw new AAIException("AAI_6114", msg);
1762 String modelVerId = modelVerVtx.<String>property("model-version-id").orElse(null);
1763 if( modelVerId == null ){
1764 String nt = modelVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
1765 if( nt != null && !nt.equals("model-ver") ){
1766 String msg = "Illegal model defined: model element pointing to nodeType: ["
1767 + nt + "], should be pointing to: [model-ver] at [" + trail + "]. ";
1768 throw new AAIException("AAI_6132", msg);
1772 Vertex firstElementVertex = null;
1774 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, modelVerVtx, "model-element");
1776 while( vertI != null && vertI.hasNext() ){
1778 firstElementVertex = vertI.next();
1782 String msg = "Illegal model defined: More than one first element defined for model-ver-id = " +
1783 modelVerId + " at [" + trail + "]. ";
1784 throw new AAIException("AAI_6132", msg);
1787 if( firstElementVertex == null ){
1788 String msg = "Could not find first model element for model-ver-id = "
1789 + modelVerId + " at [" + trail + "]. ";
1790 throw new AAIException("AAI_6132", msg);
1793 return firstElementVertex;
1795 } // End of getTopElementForSvcOrResModelVer()
1800 * Gets the named query prop over ride.
1802 * @param transId the trans id
1803 * @param fromAppId the from app id
1804 * @param namedQueryElementVertex the named query element vertex
1805 * @param instanceVertex the instance vertex
1806 * @param apiVer the api ver
1807 * @return HashMap of alternate properties to return for this element
1808 * @throws AAIException the AAI exception
1810 public Map<String,Object> getNamedQueryPropOverRide(String transId, String fromAppId,
1811 Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer )
1812 throws AAIException {
1814 // If this model-element says that they want an alternative set of properties returned, then pull that
1815 // data out of the instance vertex.
1817 Map<String,Object> altPropHash = new HashMap<>();
1819 if( namedQueryElementVertex == null ){
1820 String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() ";
1821 throw new AAIException("AAI_6114", msg);
1824 List<String> propCollectList = new ArrayList<>();
1825 Iterator <VertexProperty<Object>> vpI = namedQueryElementVertex.properties("property-collect-list");
1826 while( vpI.hasNext() ){
1827 propCollectList.add((String)vpI.next().value());
1830 for( int i = 0; i < propCollectList.size(); i++ ){
1831 String thisPropName = propCollectList.get(i);
1832 Object instanceVal = instanceVertex.<Object>property(thisPropName).orElse(null);
1833 altPropHash.put(thisPropName, instanceVal);
1838 } // End of getNamedQueryPropOverRide()
1842 * Named query constraint says stop.
1844 * @param transId the trans id
1845 * @param fromAppId the from app id
1846 * @param namedQueryElementVertex the named query element vertex
1847 * @param instanceVertex the instance vertex
1848 * @param apiVer the api ver
1849 * @return true - if a constraint was defined that has not been met by the passed instanceVertex
1850 * @throws AAIException the AAI exception
1852 public Boolean namedQueryConstraintSaysStop(String transId, String fromAppId,
1853 Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer )
1854 throws AAIException {
1856 // For each (if any) property-constraint defined for this named-query-element, we will evaluate if
1857 // the constraint is met or not-met. if there are constraints and any are not-met, then
1858 // we return "true".
1860 if( namedQueryElementVertex == null ){
1861 String msg = " null namedQueryElementVertex passed to namedQueryConstraintSaysStop() ";
1862 throw new AAIException("AAI_6114", msg);
1864 if( instanceVertex == null ){
1865 String msg = " null instanceVertex passed to namedQueryConstraintSaysStop() ";
1866 throw new AAIException("AAI_6114", msg);
1869 Iterator<Vertex> constrPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "property-constraint");
1870 if( constrPipe == null || !constrPipe.hasNext() ){
1871 // There's no "property-constraint" defined for this named-query-element. No problem.
1875 while( constrPipe.hasNext() ){
1876 Vertex constrVtx = (Vertex) constrPipe.next();
1877 // We found a property constraint that we will need to check
1878 String conType = constrVtx.<String>property("constraint-type").orElse(null);
1879 if( (conType == null) || conType.equals("")){
1880 String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
1881 throw new AAIException("AAI_6133", msg);
1883 String propName = constrVtx.<String>property("property-name").orElse(null);
1884 if( (propName == null) || propName.equals("")){
1885 String msg = " Bad property-constraint (property-name) found in Named Query definition. ";
1886 throw new AAIException("AAI_6133", msg);
1888 String propVal = constrVtx.<String>property("property-value").orElse(null);
1889 if( (propVal == null) || propVal.equals("")){
1890 String msg = " Bad property-constraint (propVal) found in Named Query definition. ";
1891 throw new AAIException("AAI_6133", msg);
1894 // See if that constraint is met or not
1895 String val = instanceVertex.<String>property(propName).orElse(null);
1900 if( conType.equals("EQUALS") ){
1901 if( !val.equals(propVal) ){
1902 // This constraint was not met
1906 else if( conType.equals("NOT-EQUALS") ){
1907 if( val.equals(propVal) ){
1908 // This constraint was not met
1913 String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
1914 throw new AAIException("AAI_6133", msg);
1920 } // End of namedQueryConstraintSaysStop()
1924 * Gets the named query extra data lookup.
1926 * @param transId the trans id
1927 * @param fromAppId the from app id
1928 * @param namedQueryElementVertex the named query element vertex
1929 * @param instanceVertex the instance vertex
1930 * @param apiVer the api ver
1931 * @return HashMap of alternate properties to return for this element
1932 * @throws AAIException the AAI exception
1934 public Map<String,Object> getNamedQueryExtraDataLookup(String transId, String fromAppId,
1935 Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer )
1936 throws AAIException {
1938 // For each (if any) related-lookup defined for this named-query-element, we will go and
1939 // and try to find it. All the related-lookup data will get put in a hash and returned.
1941 if( namedQueryElementVertex == null ){
1942 String msg = " null namedQueryElementVertex passed to getNamedQueryExtraDataLookup() ";
1943 throw new AAIException("AAI_6114", msg);
1945 if( instanceVertex == null ){
1946 String msg = " null instanceVertex passed to getNamedQueryExtraDataLookup() ";
1947 throw new AAIException("AAI_6114", msg);
1950 Map<String,Object> retHash = new HashMap<>();
1952 Iterator<Vertex> lookPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "related-lookup");
1953 if( lookPipe == null || !lookPipe.hasNext() ){
1954 // There's no "related-lookup" defined for this named-query-element. No problem.
1958 while( lookPipe.hasNext() ){
1959 Vertex relLookupVtx = (Vertex) lookPipe.next();
1960 // We found a related-lookup record to try and use
1961 String srcProp = relLookupVtx.<String>property("source-node-property").orElse(null);
1962 String srcNodeType = relLookupVtx.<String>property("source-node-type").orElse(null);
1963 srcProp = getPropNameWithAliasIfNeeded(srcNodeType, srcProp);
1965 if( (srcProp == null) || srcProp.equals("")){
1966 String msg = " Bad related-lookup (source-node-property) found in Named Query definition. ";
1967 throw new AAIException("AAI_6133", msg);
1969 String targetNodeType = relLookupVtx.<String>property("target-node-type").orElse(null);
1970 if( (targetNodeType == null) || targetNodeType.equals("")){
1971 String msg = " Bad related-lookup (targetNodeType) found in Named Query definition. ";
1972 throw new AAIException("AAI_6133", msg);
1974 String targetProp = relLookupVtx.<String>property("target-node-property").orElse(null);
1975 targetProp = getPropNameWithAliasIfNeeded(targetNodeType, targetProp);
1977 if( (targetProp == null) || targetProp.equals("")){
1978 String msg = " Bad related-lookup (target-node-property) found in Named Query definition. ";
1979 throw new AAIException("AAI_6133", msg);
1982 List<String> propCollectList = new ArrayList<>();
1983 Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list");
1984 while( vpI.hasNext() ){
1985 propCollectList.add((String)vpI.next().value());
1988 // Use the value from the source to see if we can find ONE target record using the
1989 // value from the source
1990 String valFromInstance = instanceVertex.<String>property(srcProp).orElse(null);
1991 if( valFromInstance == null ){
1992 // if there is no key to use to go look up something, we should end it here and just
1993 // note what happened - no need to try to look something up by an empty key
1994 LOGGER.debug("WARNING - the instance data node of type [" + srcNodeType
1995 + "] did not have a value for property [" + srcProp
1996 + "], so related-lookup is being abandoned.");
2000 Map<String,Object> propHash = new HashMap<String,Object>();
2001 propHash.put(targetProp, valFromInstance);
2003 Optional<Vertex> result = dbMethHelper.locateUniqueVertex(targetNodeType, propHash);
2004 if (!result.isPresent()) {
2005 // If it can't find the lookup node, don't fail, just log that it couldn't be found ---
2006 LOGGER.debug("WARNING - Could not find lookup node that corresponds to nodeType ["
2007 + targetNodeType + "] propertyName = [" + srcProp
2008 + "], propVal = [" + valFromInstance
2009 + "] so related-lookup is being abandoned.");
2013 Vertex tmpVtx = result.get();
2014 // Pick up the properties from the target vertex that they wanted us to get
2015 for( int j = 0; j < propCollectList.size(); j++ ){
2016 String tmpPropName = propCollectList.get(j);
2017 tmpPropName = getPropNameWithAliasIfNeeded(targetNodeType, tmpPropName);
2018 Object valObj = tmpVtx.<Object>property(tmpPropName).orElse(null);
2019 String lookupKey = targetNodeType + "." + tmpPropName;
2020 retHash.put(lookupKey, valObj);
2028 } // End of getNamedQueryExtraDataLookup()
2031 * Collect NQ element hash.
2033 * @param transId the trans id
2034 * @param fromAppId the from app id
2035 * @param thisLevelElemVtx the element verrtx for this level
2036 * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this nq-element vertex) from the top
2037 * @param currentHash the current hash
2038 * @param Map that got us to this point (that we will use as the base of the map we will return)
2039 * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
2040 * @param levelCounter the level counter
2041 * @return HashMap of all widget-points on a namedQuery topology with the value being the "named-query-element-uuid" for that spot.
2042 * @throws AAIException the AAI exception
2044 public Map<String, String> collectNQElementHash(String transId, String fromAppId,
2045 Vertex thisLevelElemVtx, String incomingTrail,
2046 Map<String,String> currentHash, ArrayList <String> vidsTraversed,
2047 int levelCounter ) throws AAIException {
2051 Map<String, String> thisHash = new HashMap<>();
2052 thisHash.putAll(currentHash);
2054 if( levelCounter > MAX_LEVELS ) {
2055 throw new AAIException("AAI_6125", "collectNQElementHash() has looped across more levels than allowed: " + MAX_LEVELS + ". ");
2057 String thisGuysTrail = "";
2058 String thisElemVid = thisLevelElemVtx.id().toString();
2060 // Find out what widget (and thereby what aai-node-type) this element represents.
2061 String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail );
2063 if( incomingTrail == null || incomingTrail.equals("") ){
2064 // This is the first one
2065 thisGuysTrail = thisElementNodeType;
2068 thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
2070 vidsTraversed.add(thisElemVid);
2072 String nqElementUuid = thisLevelElemVtx.<String>property("named-query-element-uuid").orElse(null);
2073 if( nqElementUuid == null || nqElementUuid.equals("") ){
2074 String msg = " named-query element UUID not found at trail = [" + incomingTrail + "].";
2075 throw new AAIException("AAI_6133", msg);
2077 thisHash.put(thisGuysTrail, nqElementUuid );
2079 // Now go "down" and look at the sub-elements pointed to so we can get their data.
2080 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element");
2081 while( vertI != null && vertI.hasNext() ){
2082 Vertex tmpVert = vertI.next();
2083 String vid = tmpVert.id().toString();
2084 Map<String,Object> elementHash = new HashMap<String, Object>();
2086 String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2087 if( connectToType != null && connectToType.equals("named-query-element") ){
2088 // This is what we would expect
2089 elementHash.put(vid, tmpVert);
2092 String msg = " named query element has [connectedTo] edge to improper nodeType= ["
2093 + connectToType + "] trail = [" + incomingTrail + "].";
2094 throw new AAIException("AAI_6133", msg);
2096 for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
2097 Vertex elVert = (Vertex)(entry.getValue());
2098 String tmpElVid = elVert.id().toString();
2099 if( !vidsTraversed.contains(tmpElVid) ){
2100 // This is one we would like to use - so we'll recursively get it's result set to add to ours
2101 Map<String, String> tmpHash = collectNQElementHash( transId, fromAppId,
2102 elVert, thisGuysTrail, currentHash, vidsTraversed, levelCounter);
2103 thisHash.putAll(tmpHash);
2109 } // End of collectNQElementHash()
2113 * Collect delete key hash.
2115 * @param transId the trans id
2116 * @param fromAppId the from app id
2117 * @param thisLevelElemVtx the element vertex at this level
2118 * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this vertex) from the top
2119 * @param currentHash the current hash
2120 * @param Map that got us to this point (that we will use as the base of the map we will return)
2121 * @param vidsTraversed the vids traversed ---- ArrayList of vertexId's that we traversed to get to this point
2122 * @param levelCounter the level counter
2123 * @param loader the db maps
2124 * @param modConstraintHash the mod constraint hash
2125 * @param overRideModelId the over ride model id
2126 * @param overRideModelVersionId the over ride model version id
2127 * @return HashMap of all widget-points on a model topology with the value being the "newDataDelFlag" for that spot.
2128 * @throws AAIException the AAI exception
2130 public Map<String, String> collectDeleteKeyHash(String transId, String fromAppId,
2131 Vertex thisLevelElemVtx, String incomingTrail,
2132 Map<String,String> currentHash, ArrayList <String> vidsTraversed,
2133 int levelCounter, Map<String, Vertex> modConstraintHash,
2134 String overRideModelId, String overRideModelVersionId )
2135 throws AAIException {
2139 Map<String, String> thisHash = new HashMap<>();
2140 thisHash.putAll(currentHash);
2142 if( levelCounter > MAX_LEVELS ) {
2143 throw new AAIException("AAI_6125", "collectDeleteKeyHash() has looped across more levels than allowed: " + MAX_LEVELS + ". ");
2145 String thisGuysTrail = "";
2146 String thisElemVid = thisLevelElemVtx.id().toString();
2147 Map<String, Vertex> modConstraintHash2Use = null;
2149 // If this element represents a resource or service model, then we will replace this element with
2150 // the "top" element of that resource or service model. That model-element already points to its
2151 // topology, so it will graft in that model's topology.
2152 // EXCEPT - if this element has "linkage-points" defined, then we need to do some extra
2153 // processing for how we join to that model and will not try to go any "deeper".
2154 List<String> linkagePtList = new ArrayList<>();
2155 Iterator <VertexProperty<Object>> vpI = thisLevelElemVtx.properties("linkage-points");
2157 // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition,
2158 // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to
2159 // get it - but only look at the first thing returned by the iterator.
2160 if( vpI.hasNext() ){
2161 String tmpLinkageThing = (String)vpI.next().value();
2162 linkagePtList = makeSureItsAnArrayList( tmpLinkageThing );
2165 if( linkagePtList != null && !linkagePtList.isEmpty() ){
2166 // Whatever this element is - we are connecting to it via a linkage-point
2167 // We will figure out what to do and then return without going any deeper
2168 String elemFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null);
2170 Set<String> linkageConnectNodeTypes = getLinkageConnectNodeTypes( linkagePtList );
2171 Iterator <?> linkNtIter = linkageConnectNodeTypes.iterator();
2172 String incTrail = "";
2173 if( incomingTrail != null && !incomingTrail.equals("") ){
2174 incTrail = incomingTrail + "|";
2177 while( linkNtIter.hasNext() ){
2178 // The 'trail' (or trails) for this element should just be the to the first-contact on the linkage point
2179 String linkTrail = incTrail + linkNtIter.next();
2180 Boolean alreadyTaggedFalse = false;
2181 if( thisHash.containsKey(linkTrail) && thisHash.get(linkTrail).equals("F") ){
2182 // some other path with a matching trail has the deleteFlag set to "F", so we do not want
2183 // to override that since our model code only uses nodeTypes to know where it is - and we
2184 // would rather do less deleting than needed instead of too much deleting.
2185 alreadyTaggedFalse = true;
2187 if( elemFlag != null && elemFlag.equals("T") && !alreadyTaggedFalse ){
2188 // This trail should be marked with an "T"
2189 thisHash.put(linkTrail, "T");
2192 thisHash.put(linkTrail, "F");
2198 // ----------------------------------------------------------------------------
2199 // If we got to here, then this was not an element that used a linkage-point
2200 // ----------------------------------------------------------------------------
2202 // Find out what widget-model (and thereby what aai-node-type) this element represents.
2203 // Even if this element is pointing to a service or resource model, it must have a
2204 // first element which is a single widget-type model.
2205 String thisElementNodeType = getModElementWidgetType( thisLevelElemVtx, incomingTrail );
2206 String firstElementModelInfo = "";
2208 vidsTraversed.add(thisElemVid);
2209 Vertex elementVtxForThisLevel = null;
2210 Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail );
2211 Vertex thisElementsModelVtx = getModelGivenModelVer( thisElementsModelVerVtx, incomingTrail );
2212 String modType = getModelTypeFromModel( thisElementsModelVtx, incomingTrail );
2213 String subModelFirstModInvId = thisElementsModelVtx.<String>property("model-invariant-id").orElse(null);
2214 String subModelFirstVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null);
2215 if( modType.equals("widget") ){
2216 if( overRideModelId != null && !overRideModelId.equals("") ){
2217 // Note - this is just to catch the correct model for the TOP node in a model since
2218 // it will have an element which will always be a widget even though the model
2219 // could be a resource or service model.
2220 firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersionId;
2223 else if( nodeTypeSupportsPersona(thisElementNodeType) ){
2224 firstElementModelInfo = "," + subModelFirstModInvId + "," + subModelFirstVerId;
2227 if( incomingTrail.equals("") ){
2228 // This is the first one
2229 thisGuysTrail = thisElementNodeType + firstElementModelInfo;
2232 thisGuysTrail = incomingTrail + "|" + thisElementNodeType + firstElementModelInfo;
2235 String tmpFlag = "F";
2236 Boolean stoppedByASvcOrResourceModelElement = false;
2237 if( modType.equals("widget") ){
2238 elementVtxForThisLevel = thisLevelElemVtx;
2239 // For the element-model for the widget at this level, record it's delete flag
2240 tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
2243 // For an element that is referring to a resource or service model, we replace
2244 // this element with the "top" element for that resource/service model so that the
2245 // topology of that resource/service model will be included in this topology.
2246 String modelVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null);
2247 if( subModelFirstModInvId == null || subModelFirstModInvId.equals("")
2248 || subModelFirstVerId == null || subModelFirstVerId.equals("") ){
2249 throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-version-id = " +
2250 modelVerId + ", at [" + incomingTrail + "]");
2253 // BUT -- if the model-element HERE at the resource/service level does NOT have
2254 // it's new-data-del-flag set to "T", then we do not need to go down into the
2255 // sub-model looking for delete-able things.
2257 tmpFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null);
2258 elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, thisGuysTrail);
2259 if( tmpFlag != null && tmpFlag.equals("T") ){
2260 modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, modConstraintHash );
2263 stoppedByASvcOrResourceModelElement = true;
2265 // For the element-model for the widget at this level, record it's delete flag
2266 tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
2269 String flag2Use = "F"; // by default we'll use "F" for the delete flag
2270 if( ! stoppedByASvcOrResourceModelElement ){
2271 // Since we haven't been stopped by a resource/service level "F", we can look at the lower level flag
2272 if( thisHash.containsKey(thisGuysTrail) ){
2273 // We've seen this spot in the topology before - do not override the delete flag if the older one is "F"
2274 // We will only over-ride it if the old one was "T" and the new one is "F" (anything but "T")
2275 String oldFlag = thisHash.get(thisGuysTrail);
2276 if( oldFlag.equals("T") && (tmpFlag != null) && tmpFlag.equals("T") ){
2277 // The old flag was "T" and the new flag is also "T"
2281 // the old flag was not "F" - so don't override it
2285 else if( (tmpFlag != null) && tmpFlag.equals("T") ){
2286 // We have not seen this one, so we can set it to "T" if that's what it is.
2291 thisHash.put(thisGuysTrail, flag2Use);
2292 if( ! stoppedByASvcOrResourceModelElement ){
2293 // Since we haven't been stopped by a resource/service level "F", we will continue to
2294 // go "down" and look at the elements pointed to so we can get their data.
2295 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set");
2296 while( vertI != null && vertI.hasNext() ){
2297 Vertex tmpVert = vertI.next();
2298 String vid = tmpVert.id().toString();
2299 Map<String,Object> elementHash = new HashMap<String, Object>();
2301 String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2302 if( connectToType != null && connectToType.equals("model-element") ){
2303 // A nice, regular old model-element
2304 elementHash.put(vid, tmpVert);
2306 else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
2307 // translate the constrained-element-set into a hash of model-element Vertex's
2308 String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
2309 if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
2310 // This constrained-element-set is being superseded by a different one
2311 Vertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
2312 elementHash = getNextStepElementsFromSet( replacementConstraintVert );
2313 // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
2314 modConstraintHash.remove(constrainedElementSetUuid);
2317 elementHash = getNextStepElementsFromSet( tmpVert );
2321 String msg = " model-element has [connectedTo] edge to improper nodeType= ["
2322 + connectToType + "] trail = [" + incomingTrail + "].";
2323 throw new AAIException("AAI_6132", msg);
2326 for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
2327 Vertex elVert = (Vertex)(entry.getValue());
2328 String tmpElVid = elVert.id().toString();
2329 String tmpElNT = getModElementWidgetType( elVert, thisGuysTrail );
2330 check4EdgeRule(tmpElNT, thisElementNodeType);
2331 if( !vidsTraversed.contains(tmpElVid) ){
2332 // This is one we would like to use - so we'll recursively get it's result set to add to ours
2333 Map<String, String> tmpHash = collectDeleteKeyHash( transId, fromAppId,
2334 elVert, thisGuysTrail,
2335 currentHash, vidsTraversed, levelCounter, modConstraintHash2Use,
2337 thisHash.putAll(tmpHash);
2344 } // End of collectDeleteKeyHash()
2348 * Gets the linkage connect node types.
2350 * @param linkagePtList the linkage pt list
2351 * @return the linkage connect node types
2352 * @throws AAIException the AAI exception
2354 public Set<String> getLinkageConnectNodeTypes(List<String> linkagePtList )
2355 throws AAIException {
2356 // linkage points are a path from the top of a model to where we link in.
2357 // This method wants to just bring back a list of distinct last items.
2358 // Ie: for the input with these two: "pserver|lag-link|l-interface" and "pserver|p-interface|l-interface"
2359 // it would just return a single item, "l-interface" since both linkage points end in that same node-type.
2361 Set<String> linkPtSet = new HashSet<>();
2363 if( linkagePtList == null ){
2364 String detail = " Bad (null) linkagePtList passed to getLinkageConnectNodeTypes() ";
2365 throw new AAIException("AAI_6125", detail);
2368 for( int i = 0; i < linkagePtList.size(); i++ ){
2369 String [] trailSteps = linkagePtList.get(i).split("\\|");
2370 if( trailSteps == null || trailSteps.length == 0 ){
2371 String detail = " Bad incomingTrail passed to getLinkageConnectNodeTypes(): [" + linkagePtList + "] ";
2372 throw new AAIException("AAI_6125", detail);
2374 String lastStepNT = trailSteps[trailSteps.length - 1];
2375 linkPtSet.add(lastStepNT);
2380 }// End getLinkageConnectNodeTypes()
2384 * Collect topology for model-ver.
2386 * @param transId the trans id
2387 * @param fromAppId the from app id
2388 * @param modelElement vertex to collect for
2389 * @param incomingTrail the incoming trail -- trail of nodeTypes/personaInfo that got us here (this vertex) from the top
2390 * @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)
2391 * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
2392 * @param levelCounter the level counter
2393 * @param loader the db maps
2394 * @param modConstraintHash the mod constraint hash
2395 * @param overRideModelInvId the override model-invariant-id
2396 * @param overRideModelVersionId the override model-version-id
2397 * @return Map of the topology
2398 * @throws AAIException the AAI exception
2400 public Multimap<String, String> collectTopology4ModelVer(String transId, String fromAppId,
2401 Vertex thisLevelElemVtx, String incomingTrail,
2402 Multimap<String,String> currentMap, List<String> vidsTraversed,
2403 int levelCounter, Map<String, Vertex> modConstraintHash,
2404 String overRideModelInvId, String overRideModelVersionId )
2405 throws AAIException {
2409 Multimap<String, String> thisMap = ArrayListMultimap.create();
2410 thisMap.putAll(currentMap);
2412 if( levelCounter > MAX_LEVELS ) {
2413 throw new AAIException("AAI_6125", "collectTopology4ModelVer() has looped across more levels than allowed: " + MAX_LEVELS + ". ");
2415 String thisGuysTrail = "";
2416 String thisElemVid = thisLevelElemVtx.id().toString();
2417 Map<String, Vertex> modConstraintHash2Use = null;
2419 // If this element represents a resource or service model, then we will replace this element with
2420 // the "top" element of that resource or service model. That model-element already points to its
2421 // topology, so it will graft in that model's topology.
2422 // EXCEPT - if this element defines "linkage-points" defined, then we need to do some extra
2423 // processing for how we join to that model.
2425 // Find out what widget-model (and thereby what aai-node-type) this element represents.
2426 // Even if this element is pointing to a service or resource model, it must have a
2427 // first element which is a single widget-type model.
2428 String firstElementModelInfo = "";
2429 String thisElementNodeType = getModElementWidgetType( thisLevelElemVtx, incomingTrail );
2430 if( nodeTypeSupportsPersona(thisElementNodeType) && overRideModelInvId != null && !overRideModelInvId.equals("") ){
2431 firstElementModelInfo = "," + overRideModelInvId + "," + overRideModelVersionId;
2434 Vertex elementVtxForThisLevel = null;
2435 Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail );
2436 String subModelFirstModInvId = "";
2437 String subModelFirstModVerId = "";
2438 String modInfo4Trail = "";
2439 String modType = getModelTypeFromModelVer( thisElementsModelVerVtx, incomingTrail );
2440 if( modType.equals("resource") || modType.equals("service") ){
2441 // For an element that is referring to a resource or service model, we replace this
2442 // this element with the "top" element for that resource/service model so that the
2443 // topology of that resource/service model gets included in this topology.
2444 // -- Note - since that top element of a service or resource model will point to a widget model,
2445 // we have to track what modelId/version it really maps so we can make our recursive call
2446 Vertex thisElementsModelVtx = getModelGivenModelVer(thisElementsModelVerVtx, incomingTrail);
2447 subModelFirstModInvId = thisElementsModelVtx.<String>property("model-invariant-id").orElse(null);
2448 subModelFirstModVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null);
2450 if( nodeTypeSupportsPersona(thisElementNodeType) ){
2451 modInfo4Trail = "," + subModelFirstModInvId + "," + subModelFirstModVerId;
2453 String modelVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null);
2454 if( subModelFirstModInvId == null || subModelFirstModInvId.equals("") || subModelFirstModVerId == null || subModelFirstModVerId.equals("") ){
2455 throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-ver-id = " + modelVerId);
2458 elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, incomingTrail);
2459 modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, modConstraintHash );
2462 elementVtxForThisLevel = thisLevelElemVtx;
2465 if( incomingTrail.equals("") ){
2466 // This is the first one
2467 thisGuysTrail = thisElementNodeType + firstElementModelInfo;
2470 thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail;
2473 // We only want to ensure that a particular element does not repeat on a single "branch".
2474 // It could show up on other branches in the case where it is a sub-model which is being
2475 // used in more than one place.
2477 List<String> thisTrailsVidsTraversed = new ArrayList <String>();
2478 thisTrailsVidsTraversed.addAll(vidsTraversed);
2479 thisTrailsVidsTraversed.add(thisElemVid);
2481 // Look at the elements pointed to at this level and add on their data
2482 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set");
2484 while( vertI != null && vertI.hasNext() ){
2485 Vertex tmpVert = vertI.next();
2486 String vid = tmpVert.id().toString();
2487 Map<String,Object> elementHash = new HashMap<String, Object>();
2488 String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2489 if( connectToType != null && connectToType.equals("model-element") ){
2490 // A nice, regular old model-element
2491 elementHash.put(vid, tmpVert);
2493 else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
2494 // translate the constrained-element-set into a hash of model-element Vertex's
2495 String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
2496 if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
2497 // This constrained-element-set is being superseded by a different one
2498 Vertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
2499 elementHash = getNextStepElementsFromSet( replacementConstraintVert );
2500 // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
2501 modConstraintHash.remove(constrainedElementSetUuid);
2504 elementHash = getNextStepElementsFromSet( tmpVert );
2508 String msg = " model element has [connectedTo] edge to improper nodeType= ["
2509 + connectToType + "] trail = [" + incomingTrail + "].";
2510 throw new AAIException("AAI_6132", msg);
2513 for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
2514 Vertex elVert = (Vertex)(entry.getValue());
2515 String tmpElVid = elVert.id().toString();
2516 String tmpElNT = getModElementWidgetType( elVert, thisGuysTrail );
2517 String tmpElStepName = getModelElementStepName( elVert, thisGuysTrail);
2519 List<String> linkagePtList = new ArrayList <String>();
2520 Iterator <VertexProperty<Object>> vpI = elVert.properties("linkage-points");
2522 // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition,
2523 // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to
2524 // get it - but only look at the first thing returned by the iterator.
2525 if( vpI.hasNext() ){
2526 String tmpLinkageThing = (String)vpI.next().value();
2527 linkagePtList = makeSureItsAnArrayList( tmpLinkageThing );
2530 if( linkagePtList != null && !linkagePtList.isEmpty() ){
2531 // This is as far as we can go, we will use the linkage point info to define the
2532 // rest of this "trail"
2533 for( int i = 0; i < linkagePtList.size(); i++ ){
2534 Multimap<String, String> tmpMap = collectTopology4LinkagePoint( transId, fromAppId,
2535 linkagePtList.get(i), thisGuysTrail, currentMap);
2536 thisMap.putAll(tmpMap);
2540 check4EdgeRule(tmpElNT, thisElementNodeType);
2541 thisMap.put(thisGuysTrail, tmpElStepName);
2542 if( !thisTrailsVidsTraversed.contains(tmpElVid) ){
2543 // This is one we would like to use - so we'll recursively get it's result set to add to ours
2544 Multimap<String, String> tmpMap = collectTopology4ModelVer( transId, fromAppId,
2545 elVert, thisGuysTrail,
2546 currentMap, thisTrailsVidsTraversed, levelCounter,
2547 modConstraintHash2Use, subModelFirstModInvId, subModelFirstModVerId );
2548 thisMap.putAll(tmpMap);
2551 String modelElementUuid = elVert.<String>property("model-element-uuid").orElse(null);
2552 String msg = "Bad Model Definition: looping model-element (model-element-uuid = [" +
2553 modelElementUuid + "]) found trying to add step: [" + tmpElStepName + "], " +
2554 " on trail = [" + thisGuysTrail + "]. ";
2555 System.out.println( msg );
2556 throw new AAIException("AAI_6132", msg);
2564 } // End of collectTopology4ModelVer()
2568 * Check 4 edge rule.
2570 * @param nodeTypeA the node type A
2571 * @param nodeTypeB the node type B
2572 * @param loader the db maps
2573 * @throws AAIException the AAI exception
2575 public void check4EdgeRule( String nodeTypeA, String nodeTypeB) throws AAIException {
2576 // Throw an exception if there is no defined edge rule for this combination of nodeTypes in DbEdgeRules.
2578 final EdgeRules edgeRules = EdgeRules.getInstance();
2580 if( !edgeRules.hasEdgeRule(nodeTypeA, nodeTypeB)
2581 && !edgeRules.hasEdgeRule(nodeTypeB, nodeTypeA) ){
2582 // There's no EdgeRule for this -- find out if one of the nodeTypes is invalid or if
2583 // they are valid, but there's just no edgeRule for them.
2585 loader.introspectorFromName(nodeTypeA);
2586 } catch (AAIUnknownObjectException e) {
2587 String emsg = " Unrecognized nodeType aa [" + nodeTypeA + "]\n";
2588 throw new AAIException("AAI_6115", emsg);
2591 loader.introspectorFromName(nodeTypeB);
2592 } catch (AAIUnknownObjectException e) {
2593 String emsg = " Unrecognized nodeType bb [" + nodeTypeB + "]\n";
2594 throw new AAIException("AAI_6115", emsg);
2597 String msg = " No Edge Rule found for this pair of nodeTypes (order does not matter) ["
2598 + nodeTypeA + "], [" + nodeTypeB + "].";
2599 throw new AAIException("AAI_6120", msg);
2607 * Collect topology 4 linkage point.
2609 * @param transId the trans id
2610 * @param fromAppId the from app id
2611 * @param linkagePointStr -- Note it is in reverse order from where we connect to it.
2612 * @param incomingTrail -- trail of nodeTypes that got us here (this vertex) from the top
2613 * @param currentMap the current map -- that got us to this point (that we will use as the base of the map we will return)
2614 * @param loader the db maps
2615 * @return Map of the topology
2616 * @throws AAIException the AAI exception
2618 public Multimap<String, String> collectTopology4LinkagePoint(String transId, String fromAppId,
2619 String linkagePointStrVal, String incomingTrail, Multimap<String,String> currentMap)
2620 throws AAIException {
2622 Multimap<String, String> thisMap = ArrayListMultimap.create();
2623 thisMap.putAll(currentMap);
2624 String thisGuysTrail = incomingTrail;
2626 // NOTE - "trails" can have multiple parts now since we track persona info for some.
2627 // We just want to look at the node type info - which would be the piece
2628 // before any commas (if there are any).
2630 String [] trailSteps = thisGuysTrail.split("\\|");
2631 if( trailSteps == null || trailSteps.length == 0 ){
2632 throw new AAIException("AAI_6125", "Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + "] ");
2634 String lastStepString = trailSteps[trailSteps.length - 1];
2635 String [] stepPieces = lastStepString.split(",");
2636 String lastStepNT = stepPieces[0];
2638 // It is assumed that the linkagePoint string will be a pipe-delimited string where each
2639 // piece is an AAIProperties.NODE_TYPE. For now, the first thing to connect to is what is on the farthest right.
2640 // Example: linkagePoint = "pserver|p-interface|l-interface" would mean that we're connecting to the l-interface
2641 // but that after that, we connect to a p-interface followed by a pserver.
2642 // It might have been more clear to define it in the other direction, but for now, that is it. (16-07)
2643 String linkagePointStr = linkagePointStrVal;
2645 // We are getting these with more than linkage thing in one string.
2646 // Ie. "pserver|lag-interface|l-interface, pserver|p-interface|l-interface, vlan|l-interface"
2647 linkagePointStr = linkagePointStr.replace("[", "");
2648 linkagePointStr = linkagePointStr.replace("]", "");
2649 linkagePointStr = linkagePointStr.replace(" ", "");
2651 String [] linkage = linkagePointStr.split("\\,");
2652 for( int x = 0; x < linkage.length; x++ ){
2653 lastStepNT = stepPieces[0];
2654 String thisStepNT = "";
2655 String [] linkageSteps = linkage[x].split("\\|");
2656 if( linkageSteps == null || linkageSteps.length == 0 ){
2657 throw new AAIException("AAI_6125", "Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + linkagePointStr + "] ");
2659 for( int i=(linkageSteps.length - 1); i >= 0; i-- ){
2660 thisStepNT = linkageSteps[i];
2661 check4EdgeRule(lastStepNT, thisStepNT);
2662 thisMap.put(thisGuysTrail, thisStepNT);
2663 thisGuysTrail = thisGuysTrail + "|" + thisStepNT;
2664 lastStepNT = thisStepNT;
2669 } // End of collectTopology4LinkagePoint()
2673 * Gets the next step elements from set.
2675 * @param constrElemSetVtx the constr elem set vtx
2676 * @return Hash of the set of model-elements this set represents
2677 * @throws AAIException the AAI exception
2679 public Map<String,Object> getNextStepElementsFromSet( Vertex constrElemSetVtx )
2680 throws AAIException {
2681 // Take a constrained-element-set and figure out the total set of all the possible elements that it
2682 // represents and return them as a Hash.
2684 Map<String,Object> retElementHash = new HashMap<String, Object>();
2686 if( constrElemSetVtx == null ){
2687 String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx ";
2688 throw new AAIException("AAI_6125", msg);
2691 String constrNodeType = constrElemSetVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2692 String constrElemSetUuid = constrElemSetVtx.<String>property("constrained-element-set-uuid").orElse(null);
2693 if( constrNodeType == null || !constrNodeType.equals("constrained-element-set") ){
2694 String msg = " getNextStepElementsFromSet() called with wrong type model: [" + constrNodeType + "]. ";
2695 throw new AAIException("AAI_6125", msg);
2698 ArrayList <Vertex> choiceSetVertArray = new ArrayList<Vertex>();
2699 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, constrElemSetVtx, "element-choice-set");
2701 while( vertI != null && vertI.hasNext() ){
2702 Vertex choiceSetVertex = vertI.next();
2703 String constrSetType = choiceSetVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2704 if( constrSetType != null && constrSetType.equals("element-choice-set") ){
2705 choiceSetVertArray.add(choiceSetVertex);
2710 if( setCount == 0 ){
2711 String msg = "No element-choice-set found under constrained-element-set-uuid = " + constrElemSetUuid;
2712 throw new AAIException("AAI_6132", msg);
2715 // Loop through each choice-set and grab the model-elements
2716 for( int i = 0; i < setCount; i++ ){
2717 Vertex choiceSetVert = choiceSetVertArray.get(i);
2718 Iterator<Vertex> mVertI = this.traverseIncidentEdges(EdgeType.TREE, choiceSetVert, "model-element");
2720 while( mVertI != null && mVertI.hasNext() ){
2721 Vertex tmpElVertex = mVertI.next();
2722 String elNodeType = tmpElVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2723 if( elNodeType != null && elNodeType.equals("model-element") ){
2724 String tmpVid = tmpElVertex.id().toString();
2725 retElementHash.put(tmpVid, tmpElVertex);
2729 // unsupported node type found for this choice-set
2730 String msg = "Unsupported nodeType (" + elNodeType
2731 + ") found under choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
2732 throw new AAIException("AAI_6132", msg);
2737 String msg = "No model-elements found in choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
2738 throw new AAIException("AAI_6132", msg);
2742 return retElementHash;
2744 } // End of getNextStepElementsFromSet()
2749 * Gen topo map 4 named Q.
2751 * @param transId the trans id
2752 * @param fromAppId the from app id
2753 * @param queryVertex the query vertex
2754 * @param namedQueryUuid the named query uuid
2755 * @return MultiMap of valid next steps for each potential query-element
2756 * @throws AAIException the AAI exception
2758 public Multimap<String, String> genTopoMap4NamedQ(String transId, String fromAppId,
2759 Vertex queryVertex, String namedQueryUuid )
2760 throws AAIException {
2762 if( queryVertex == null ){
2763 throw new AAIException("AAI_6125", "null queryVertex passed to genTopoMap4NamedQ()");
2766 Multimap<String, String> initialEmptyMap = ArrayListMultimap.create();
2767 List<String> vidsTraversed = new ArrayList<>();
2769 Vertex firstElementVertex = null;
2770 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVertex, "named-query-element");
2772 while( vertI != null && vertI.hasNext() ){
2774 firstElementVertex = vertI.next();
2778 throw new AAIException("AAI_6133", "Illegal query defined: More than one first element defined for = " + namedQueryUuid);
2781 if( firstElementVertex == null ){
2782 throw new AAIException("AAI_6114", "Could not find first query element = " + namedQueryUuid);
2785 Vertex modVtx = getModelThatNqElementRepresents( firstElementVertex, "" );
2786 String modelType = getModelTypeFromModel( modVtx, "" );
2787 if( ! modelType.equals("widget") ){
2788 throw new AAIException("AAI_6133", "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = "
2792 Multimap<String, String> collectedMap = collectTopology4NamedQ( transId, fromAppId,
2793 firstElementVertex, "",
2794 initialEmptyMap, vidsTraversed, 0);
2796 return collectedMap;
2798 } // End of genTopoMap4NamedQ()
2803 * Collect topology 4 named Q.
2805 * @param transId the trans id
2806 * @param fromAppId the from app id
2807 * @param thisLevelElemVtx the model element vertex for this level
2808 * @param levelCounter the level counter
2810 * @throws AAIException the AAI exception
2812 public Multimap<String, String> collectTopology4NamedQ(String transId, String fromAppId,
2813 Vertex thisLevelElemVtx, String incomingTrail,
2814 Multimap<String,String> currentMap, List<String> vidsTraversed, int levelCounter )
2815 throws AAIException {
2819 Multimap<String, String> thisMap = ArrayListMultimap.create();
2820 thisMap.putAll(currentMap);
2822 String thisElemVid = thisLevelElemVtx.id().toString();
2823 if( levelCounter > MAX_LEVELS ) {
2824 throw new AAIException("AAI_6125", "collectModelStructure() has looped across more levels than allowed: " + MAX_LEVELS + ". ");
2826 String thisGuysTrail = "";
2828 // find out what widget (and thereby what aai-node-type) this element represents
2829 String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail );
2831 if( incomingTrail.equals("") ){
2832 // This is the first one
2833 thisGuysTrail = thisElementNodeType;
2836 thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
2839 vidsTraversed.add(thisElemVid);
2841 // Look at the elements pointed to at this level and add on their data
2842 Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element");
2843 while( vertI != null && vertI.hasNext() ){
2844 Vertex tmpVert = vertI.next();
2845 String tmpVid = tmpVert.id().toString();
2846 String tmpElNT = getNqElementWidgetType( transId, fromAppId, tmpVert, thisGuysTrail );
2847 thisMap.put(thisGuysTrail, tmpElNT);
2848 if( !vidsTraversed.contains(tmpVid) ){
2849 // This is one we would like to use - so we'll recursively get it's result set to add to ours
2850 Multimap<String, String> tmpMap = collectTopology4NamedQ( transId, fromAppId,
2851 tmpVert, thisGuysTrail,
2852 currentMap, vidsTraversed, levelCounter);
2853 thisMap.putAll(tmpMap);
2859 } // End of collectTopology4NamedQ()
2863 * Gets the model that NamedQuery element represents.
2865 * @param elementVtx the NQ element vtx
2866 * @param elementTrail the element trail
2867 * @return the model that element represents
2868 * @throws AAIException the AAI exception
2870 public Vertex getModelThatNqElementRepresents(Vertex elementVtx, String elementTrail )
2871 throws AAIException {
2873 // Get the model that a named-query element represents
2874 Vertex modVtx = null;
2875 Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model");
2877 while( mvertI != null && mvertI.hasNext() ){
2879 modVtx = mvertI.next();
2883 String msg = "Illegal element defined: More than one model pointed to by a single named-query-element at [" +
2884 elementTrail + "].";
2885 throw new AAIException("AAI_6125", msg);
2888 if( modVtx == null ){
2889 String msg = "Bad named-query definition: Could not find model for element. ";
2890 if( !elementTrail.equals("") ){
2891 msg = "Bad named-query definition: Could not find model for named-query-element at [" + elementTrail + "].";
2893 throw new AAIException("AAI_6132", msg);
2896 String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2897 if( (nodeType != null) && nodeType.equals("model") ){
2901 String msg = "Illegal Named Query element defined: expecting a 'model', but found 'isA' edge pointing to nodeType = " +
2902 nodeType + "] at [" + elementTrail + "].";
2903 throw new AAIException("AAI_6125", msg);
2906 }// getModelThatNqElementRepresents()
2910 * Gets the model-ver that element represents.
2912 * @param elementVtx the element vtx
2913 * @param elementTrail the element trail
2914 * @return the model-ver that element represents
2915 * @throws AAIException the AAI exception
2917 public Vertex getModelVerThatElementRepresents(Vertex elementVtx, String elementTrail )
2918 throws AAIException {
2920 // Get the model-ver that an element represents
2921 Vertex modVerVtx = null;
2922 Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model-ver");
2924 while( mvertI != null && mvertI.hasNext() ){
2926 modVerVtx = mvertI.next();
2930 String msg = "Illegal element defined: More than one model pointed to by a single element at [" +
2931 elementTrail + "].";
2932 throw new AAIException("AAI_6125", msg);
2935 if( modVerVtx == null ){
2936 String msg = "Bad model definition: Could not find model-ver for model-element. ";
2937 if( !elementTrail.equals("") ){
2938 msg = "Bad model definition: Could not find model-VER for model-element at [" + elementTrail + "].";
2940 throw new AAIException("AAI_6132", msg);
2943 String nodeType = modVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);
2944 if( (nodeType != null) && nodeType.equals("model-ver") ){
2948 String msg = "Illegal model-element defined: expecting a 'model-ver', but found 'isA' edge pointing to nodeType = " +
2949 nodeType + "] at [" + elementTrail + "].";
2950 throw new AAIException("AAI_6125", msg);
2953 }// getModelVerThatElementRepresents()
2958 * Gets the model that is parent to model-ver node.
2960 * @param modVerVtx the model-ver vtx
2961 * @param elementTrail the element trail
2962 * @return the model that element represents
2963 * @throws AAIException the AAI exception
2965 public Vertex getModelGivenModelVer(Vertex modVerVtx, String elementTrail )
2966 throws AAIException {
2968 // Get the parent model for this "model-ver" node
2969 Vertex modVtx = null;
2970 Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, modVerVtx, "model");
2972 while( mvertI != null && mvertI.hasNext() ){
2974 modVtx = mvertI.next();
2978 String msg = "Illegal model-ver node defined: More than one model points to it with a 'has' edge [" +
2979 elementTrail + "].";
2980 throw new AAIException("AAI_6125", msg);
2983 if( modVtx == null ){
2984 String msg = "Bad model-ver node: Could not find parent model. ";
2985 if( !elementTrail.equals("") ){
2986 msg = "Bad model-ver node: Could not find parent model. [" + elementTrail + "].";
2988 throw new AAIException("AAI_6132", msg);
2991 String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null);;
2992 if( (nodeType != null) && nodeType.equals("model") ){
2993 // Found what we were looking for.
2997 // Something is amiss
2998 String msg = " Could not find parent model node for model-ver node at [" +
2999 elementTrail + "].";
3000 throw new AAIException("AAI_6125", msg);
3004 }// getModelGivenModelVer()
3009 * Gets the model type.
3011 * @param modelVtx the model vtx
3012 * @param elementTrail the element trail
3013 * @return the model type
3014 * @throws AAIException the AAI exception
3016 public String getModelTypeFromModel(Vertex modelVtx, String elementTrail )
3017 throws AAIException {
3019 // Get the model-type from a model vertex
3020 if( modelVtx == null ){
3021 String msg = " null modelVtx passed to getModelTypeFromModel() ";
3022 throw new AAIException("AAI_6114", msg);
3025 String modelType = modelVtx.<String>property("model-type").orElse(null);
3026 if( (modelType == null) || modelType.equals("") ){
3027 String msg = "Could not find model-type for model encountered at [" + elementTrail + "].";
3028 throw new AAIException("AAI_6132", msg);
3031 if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){
3032 String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "].";
3033 throw new AAIException("AAI_6132", msg);
3038 }// getModelTypeFromModel()
3043 * Gets the model type given model-ver
3045 * @param modelVerVtx the model-ver vtx
3046 * @param elementTrail the element trail
3047 * @return the model type
3048 * @throws AAIException the AAI exception
3050 public String getModelTypeFromModelVer(Vertex modelVerVtx, String elementTrail )
3051 throws AAIException {
3053 // Get the model-type given a model-ver vertex
3054 if( modelVerVtx == null ){
3055 String msg = " null modelVerVtx passed to getModelTypeFromModelVer() ";
3056 throw new AAIException("AAI_6114", msg);
3059 Vertex modVtx = getModelGivenModelVer( modelVerVtx, elementTrail );
3060 String modelType = modVtx.<String>property("model-type").orElse(null);
3061 if( (modelType == null) || modelType.equals("") ){
3062 String msg = "Could not find model-type for model encountered at [" + elementTrail + "].";
3063 throw new AAIException("AAI_6132", msg);
3066 if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){
3067 String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "].";
3068 throw new AAIException("AAI_6132", msg);
3073 }// getModelTypeFromModelVer()
3078 * Gets the model-element step name.
3080 * @param elementVtx the model-element vtx
3081 * @param elementTrail the element trail
3082 * @param loader the db maps
3083 * @return the element step name
3084 * @throws AAIException the AAI exception
3086 public String getModelElementStepName(Vertex elementVtx, String elementTrail)
3087 throws AAIException {
3089 // Get the "step name" for a model-element
3090 // Step names look like this for widget-models: AAIProperties.NODE_TYPE
3091 // Step names look like this for resource/service models: "aai-node-type,model-invariant-id,model-version-id"
3092 // NOTE -- if the element points to a resource or service model, then we'll return the
3093 // widget-type of the first element (crown widget) for that model.
3094 String thisElementNodeType = "?";
3095 Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail );
3096 String modelType = getModelTypeFromModelVer( modVerVtx, elementTrail );
3098 if( modelType == null ){
3099 String msg = " could not determine modelType in getModelElementStepName(). elementTrail = [" + elementTrail + "].";
3100 throw new AAIException("AAI_6132", msg);
3103 if( modelType.equals("widget") ){
3104 // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type
3105 thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null);
3106 if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
3107 String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
3108 throw new AAIException("AAI_6132", msg);
3110 return thisElementNodeType;
3112 else if( modelType.equals("resource") || modelType.equals("service") ){
3113 Vertex modVtx = getModelGivenModelVer( modVerVtx, elementTrail );
3114 String modInvId = modVtx.<String>property("model-invariant-id").orElse(null);
3115 String modVerId = modVerVtx.<String>property("model-version-id").orElse(null);
3116 Vertex relatedTopElementModelVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail );
3117 Vertex relatedModelVtx = getModelVerThatElementRepresents( relatedTopElementModelVtx, elementTrail );
3118 thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null);
3120 if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
3121 String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
3122 throw new AAIException("AAI_6132", msg);
3125 String stepName = "";
3126 if( nodeTypeSupportsPersona(thisElementNodeType) ){
3127 // This nodeType that this resource or service model refers to does support persona-related fields, so
3128 // we will use model-invariant-id and model-version-id as part of the step name.
3129 stepName = thisElementNodeType + "," + modInvId + "," + modVerId;
3132 stepName = thisElementNodeType;
3137 String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
3138 throw new AAIException("AAI_6132", msg);
3141 }// getModelElementStepName()
3146 * Node type supports persona.
3148 * @param nodeType the node type
3149 * @param loader the db maps
3150 * @return the boolean
3151 * @throws AAIException the AAI exception
3153 public Boolean nodeTypeSupportsPersona(String nodeType)
3154 throws AAIException {
3156 if( nodeType == null || nodeType.equals("") ){
3159 Introspector obj = null;
3161 obj = loader.introspectorFromName(nodeType);
3162 } catch (AAIUnknownObjectException e) {
3163 String emsg = " Unrecognized nodeType [" + nodeType + "]\n";
3164 throw new AAIException("AAI_6115", emsg);
3167 Collection <String> props4ThisNT = loader.introspectorFromName(nodeType).getProperties();
3168 if( !props4ThisNT.contains(addDBAliasedSuffix("model-invariant-id")) || !props4ThisNT.contains(addDBAliasedSuffix("model-version-id")) ){
3175 }// nodeTypeSupportsPersona()
3179 * Gets a Named Query element's widget type.
3181 * @param elementVtx the named-query element vtx
3182 * @param elementTrail the element trail
3183 * @return the element widget type
3184 * @throws AAIException the AAI exception
3186 public String getNqElementWidgetType(String transId, String fromAppId,
3187 Vertex elementVtx, String elementTrail )
3188 throws AAIException {
3190 String thisNqElementWidgetType = "";
3191 // Get the associated node-type for the model pointed to by a named-query-element.
3192 // NOTE -- if the element points to a resource or service model, then we'll return the
3193 // widget-type of the first element (crown widget) for that model.
3194 Vertex modVtx = getModelThatNqElementRepresents( elementVtx, elementTrail );
3195 String modelType = getModelTypeFromModel( modVtx, elementTrail );
3197 if( modelType == null || !modelType.equals("widget") ){
3198 String emsg = " Model Type must be 'widget' for NamedQuery elements. Found [" + modelType + "] at [" +
3199 elementTrail + "]\n";
3200 throw new AAIException("AAI_6132", emsg);
3203 // For a Widget model, the nodeType is just mapped to the model-element.model-name
3204 List<Vertex> modVerVtxArr = getModVersUsingModel(transId, fromAppId, modVtx);
3205 if( modVerVtxArr != null && !modVerVtxArr.isEmpty() ){
3206 thisNqElementWidgetType = (modVerVtxArr.get(0)).<String>property("model-name").orElse(null);
3208 if( thisNqElementWidgetType == null || thisNqElementWidgetType.equals("") ){
3209 String emsg = " Widget type could not be determined at [" + elementTrail + "]\n";
3210 throw new AAIException("AAI_6132", emsg);
3213 return thisNqElementWidgetType;
3218 }// End getNqElementWidgetType()
3222 * Gets a model-element's top widget type.
3224 * @param elementVtx the model element vtx
3225 * @param elementTrail the element trail
3226 * @return the element widget type
3227 * @throws AAIException the AAI exception
3229 public String getModElementWidgetType(Vertex elementVtx, String elementTrail )
3230 throws AAIException {
3232 // Get the associated node-type for the model-ver pointed to by a model-element.
3233 // NOTE -- if the element points to a resource or service model, then we'll return the
3234 // widget-type of the first element (crown widget) for that model.
3235 Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail );
3236 String thisElementNodeType = getModelVerTopWidgetType( modVerVtx, elementTrail );
3237 return thisElementNodeType;
3239 }// End getModElementWidgetType()
3243 * Gets the node using unique identifier
3245 * @param transId the trans id
3246 * @param fromAppId the from app id
3247 * @param nodeType the nodeType
3248 * @param idPropertyName the property name of the unique identifier
3249 * @param uniqueIdVal the UUID value
3250 * @return unique vertex found using UUID
3251 * @throws AAIException the AAI exception
3253 public Vertex getNodeUsingUniqueId(String transId, String fromAppId,
3254 String nodeType, String idPropertyName, String uniqueIdVal )
3255 throws AAIException {
3257 // Given a unique identifier, get the Vertex
3258 if( uniqueIdVal == null || uniqueIdVal.equals("") ){
3259 String emsg = " Bad uniqueIdVal passed to getNodeUsingUniqueId(): ["
3260 + uniqueIdVal + "]\n";
3261 throw new AAIException("AAI_6118", emsg);
3264 if( idPropertyName == null || idPropertyName.equals("") ){
3265 String emsg = " Bad idPropertyName passed to getNodeUsingUniqueId(): ["
3266 + idPropertyName + "]\n";
3267 throw new AAIException("AAI_6118", emsg);
3270 if( nodeType == null || nodeType.equals("") ){
3271 String emsg = " Bad nodeType passed to getNodeUsingUniqueId(): ["
3273 throw new AAIException("AAI_6118", emsg);
3276 Vertex uniqVtx = null;
3277 Iterable <?> uniqVerts = null;
3278 uniqVerts = engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,nodeType).has(idPropertyName,uniqueIdVal).toList();
3279 if( uniqVerts == null ){
3280 String emsg = "Node could not be found for nodeType = [" + nodeType
3281 + "], propertyName = [" + idPropertyName
3282 + "], propertyValue = [" + uniqueIdVal + "]\n";
3283 throw new AAIException("AAI_6114", emsg);
3287 Iterator <?> uniqVertsIter = uniqVerts.iterator();
3288 if( !uniqVertsIter.hasNext() ){
3289 String emsg = "Node could not be found for nodeType = [" + nodeType
3290 + "], propertyName = [" + idPropertyName
3291 + "], propertyValue = [" + uniqueIdVal + "]\n";
3292 throw new AAIException("AAI_6114", emsg);
3295 while( uniqVertsIter.hasNext() ){
3297 uniqVtx = (Vertex) uniqVertsIter.next();
3299 String emsg = "More than one node found for nodeType = [" + nodeType
3300 + "], propertyName = [" + idPropertyName
3301 + "], propertyValue = [" + uniqueIdVal + "]\n";
3302 throw new AAIException("AAI_6132", emsg);
3309 }// End getNodeUsingUniqueId()
3313 * Gets the model-ver nodes using name.
3315 * @param transId the trans id
3316 * @param fromAppId the from app id
3317 * @param modelName the model name
3318 * @return the model-ver's that use this name
3319 * @throws AAIException the AAI exception
3321 public List<Vertex> getModelVersUsingName(String transId, String fromAppId,
3323 throws AAIException {
3325 // Given a "model-name", find the model-ver vertices that this maps to
3326 if( modelName == null || modelName.equals("") ){
3327 String emsg = " Bad modelName passed to getModelVersUsingName(): ["
3328 + modelName + "]\n";
3329 throw new AAIException("AAI_6118", emsg);
3332 List<Vertex> retVtxArr = new ArrayList<>();
3333 Iterator<Vertex> modVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName);
3334 if( !modVertsIter.hasNext() ){
3335 String emsg = "Model-ver record(s) could not be found for model-ver data passed. model-name = [" +
3337 throw new AAIException("AAI_6132", emsg);
3340 while( modVertsIter.hasNext() ){
3341 Vertex tmpModelVerVtx = (Vertex) modVertsIter.next();
3342 retVtxArr.add(tmpModelVerVtx);
3348 }// End getModelVersUsingName()
3352 * Gets the model-ver nodes using model-invariant-id.
3354 * @param transId the trans id
3355 * @param fromAppId the from app id
3356 * @param model-invariant-id (uniquely identifies a model)
3357 * @return the model-ver's defined for the corresponding model
3358 * @throws AAIException the AAI exception
3360 public Iterator<Vertex> getModVersUsingModelInvId(String transId, String fromAppId,
3362 throws AAIException {
3364 // Given a "model-invariant-id", find the model-ver nodes that this maps to
3365 if( modelInvId == null || modelInvId.equals("") ){
3366 String emsg = " Bad model-invariant-id passed to getModVersUsingModelInvId(): ["
3367 + modelInvId + "]\n";
3368 throw new AAIException("AAI_6118", emsg);
3371 Vertex modVtx = getNodeUsingUniqueId(transId, fromAppId, "model", "model-invariant-id", modelInvId);
3372 List<Vertex> retVtxArr = getModVersUsingModel(transId, fromAppId, modVtx);
3373 if( retVtxArr == null || retVtxArr.isEmpty() ){
3374 String emsg = " Model-ver record(s) could not be found attached to model with model-invariant-id = [" +
3376 throw new AAIException("AAI_6132", emsg);
3379 return retVtxArr.iterator();
3380 }// End getModVersUsingModelInvId()
3384 * Gets the model-ver nodes using a model node.
3386 * @param transId the trans id
3387 * @param fromAppId the from app id
3388 * @param model vertex
3389 * @return the model-ver's defined for the corresponding model
3390 * @throws AAIException the AAI exception
3392 public List<Vertex> getModVersUsingModel(String transId, String fromAppId,
3394 throws AAIException {
3396 if( modVtx == null ){
3397 String emsg = " Null model vertex passed to getModVersUsingModel(): ";
3398 throw new AAIException("AAI_6118", emsg);
3401 List<Vertex> retVtxArr = new ArrayList<>();
3402 Iterator<Vertex> modVerVertsIter = this.traverseIncidentEdges(EdgeType.TREE, modVtx, "model-ver");
3403 if(!modVerVertsIter.hasNext()){
3404 String modelInvId = modVtx.<String>property("model-invariant-id").orElse(null);
3405 String emsg = "Model-ver record(s) could not be found attached to model with model-invariant-id = [" +
3407 throw new AAIException("AAI_6132", emsg);
3410 while( modVerVertsIter.hasNext() ){
3411 Vertex tmpModelVtx = (Vertex) modVerVertsIter.next();
3412 retVtxArr.add(tmpModelVtx);
3418 }// End getModVersUsingModel()
3421 * Gets the model-version-ids using model-name.
3423 * @param transId the trans id
3424 * @param fromAppId the from app id
3425 * @param modelName the model name
3426 * @return the model uuids using name
3427 * @throws AAIException the AAI exception
3429 public List<String> getModelVerIdsUsingName( String transId, String fromAppId,
3431 throws AAIException {
3433 // Given a model-name find the model-ver nodes that it maps to
3434 if( modelName == null || modelName.equals("") ){
3435 String emsg = " Bad modelName passed to getModelVerIdsUsingName(): ["
3436 + modelName + "]\n";
3437 throw new AAIException("AAI_6118", emsg);
3440 List<String> retArr = new ArrayList<>();
3441 Iterator<Vertex> modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName);
3442 if( !modVerVertsIter.hasNext() ){
3443 String emsg = " model-ver record(s) could not be found for model data passed. model-name = [" +
3445 throw new AAIException("AAI_6114", emsg);
3448 while( modVerVertsIter.hasNext() ){
3449 Vertex modelVerVtx = (Vertex) modVerVertsIter.next();
3450 String tmpUuid = modelVerVtx.<String>property("model-version-id").orElse(null);
3451 if( (tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid) ){
3452 retArr.add(tmpUuid);
3457 if( retArr.isEmpty() ){
3458 String emsg = "No model-ver record found for model-name = ["
3459 + modelName + "]\n";
3460 throw new AAIException("AAI_6132", emsg);
3464 }// End getModelVerIdsUsingName()
3468 * Gets the model top widget type.
3470 * @param transId the trans id
3471 * @param fromAppId the from app id
3472 * @param modelVersionId the model-version-id
3473 * @param modelInvId the model-invariant-id
3474 * @param modelName the model-name
3475 * @return the model top widget type
3476 * @throws AAIException the AAI exception
3478 public String getModelVerTopWidgetType( String transId, String fromAppId,
3479 String modelVersionId, String modelInvId, String modelName )
3480 throws AAIException {
3482 // Could be given a model-ver's key info (model-version-id), OR, just a (non-unique) model-name,
3483 // Or just a model-invariant-id (which could have multiple model-ver records under it).
3484 // In any case, they should only map to one single "top" node-type for the first element.
3486 String nodeType = "?";
3487 Iterator<Vertex> modVerVertsIter;
3489 if( modelVersionId != null && !modelVersionId.equals("") ){
3490 // this would be the best - we can just look up the model-ver records directly
3491 modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-version-id",modelVersionId);
3493 else if( modelName != null && !modelName.equals("") ){
3494 modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName);
3496 else if( modelInvId != null && !modelInvId.equals("") ){
3497 modVerVertsIter = getModVersUsingModelInvId(transId, fromAppId, modelInvId);
3500 String msg = "Neither modelVersionId, modelInvariantId, nor modelName passed to: getModelVerTopWidgetType() ";
3501 throw new AAIException("AAI_6120", msg);
3504 if( !modVerVertsIter.hasNext() ){
3505 String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId +
3506 "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n";
3507 throw new AAIException("AAI_6114", emsg);
3511 if( !modVerVertsIter.hasNext() ){
3512 String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId +
3513 "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n";
3514 throw new AAIException("AAI_6114", emsg);
3516 while( modVerVertsIter.hasNext() ){
3517 Vertex tmpModVerVtx = (Vertex) modVerVertsIter.next();
3518 String tmpNT = getModelVerTopWidgetType( tmpModVerVtx, "" );
3519 if( lastNT != null && !lastNT.equals("") ){
3520 if( !lastNT.equals(tmpNT) ){
3521 String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT
3522 + ") found for model data passed. (" +
3523 " modelVersionId = [" + modelVersionId +
3524 "], modelId = [" + modelInvId +
3525 "], modelName = [" + modelName +
3527 throw new AAIException("AAI_6114", emsg);
3537 }// End getModelVerTopWidgetType()
3541 * Gets the widget type that this model-ver starts with.
3543 * @param modVerVtx the model-version vtx
3544 * @param elementTrail the element trail
3545 * @return the widget type of the starting node of this model
3546 * @throws AAIException the AAI exception
3548 public String getModelVerTopWidgetType(Vertex modVerVtx, String elementTrail )
3549 throws AAIException {
3550 // Get the associated nodeType (Ie. aai-node-type / widget-type) for a model-ver.
3551 // NOTE -- if the element points to a resource or service model, then we'll return the
3552 // widget-type of the first element (crown widget) for that model.
3553 String modelType = getModelTypeFromModelVer( modVerVtx, elementTrail );
3554 if( modelType == null ){
3555 String msg = " Could not determine modelType in getModelVerTopWidgetType(). elementTrail = [" + elementTrail + "].";
3556 throw new AAIException("AAI_6132", msg);
3559 String thisElementNodeType = "?";
3560 if( modelType.equals("widget") ){
3561 // NOTE: for models that have model-type = "widget", their child model-ver nodes will
3562 // have "model-name" which maps directly to aai-node-type (all model-ver's under one
3563 // model should start with the same widget-type, so we only need to look at one).
3564 thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null);
3565 if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
3566 String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
3567 throw new AAIException("AAI_6132", msg);
3570 else if( modelType.equals("resource") || modelType.equals("service") ){
3571 Vertex relatedTopElementVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail );
3572 Vertex relatedModVerVtx = getModelVerThatElementRepresents( relatedTopElementVtx, elementTrail );
3573 thisElementNodeType = relatedModVerVtx.<String>property("model-name").orElse(null);
3574 if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
3575 String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
3576 throw new AAIException("AAI_6132", msg);
3580 String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
3581 throw new AAIException("AAI_6132", msg);
3584 return thisElementNodeType;
3586 }// getModelVerTopWidgetType()
3592 * @param transId the trans id
3593 * @param fromAppId the from app id
3594 * @param modelNameVersionId the model name version id
3595 * @param apiVersion the api version
3596 * @throws AAIException the AAI exception
3598 public void validateModel(String transId, String fromAppId, String modelVersionIdVal, String apiVersion )
3599 throws AAIException {
3601 // Note - this will throw an exception if the model either can't be found, or if
3602 // we can't figure out its topology map.
3603 Vertex modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver",
3604 "model-version-id", modelVersionIdVal);
3605 if( modelVerVtx == null ){
3606 String msg = " Could not find model-ver with modelVersionId = [" + modelVersionIdVal + "].";
3607 throw new AAIException("AAI_6114", msg);
3610 Multimap<String, String> topoMap = genTopoMap4ModelVer( transId, fromAppId,
3611 modelVerVtx, modelVersionIdVal);
3612 String msg = " modelVer [" + modelVersionIdVal + "] topo multiMap looks like: \n[" + topoMap + "]";
3613 System.out.println("INFO -- " + msg );
3617 }// End validateModel()
3621 * Validate named query.
3623 * @param transId the trans id
3624 * @param fromAppId the from app id
3625 * @param namedQueryUuid the named query uuid
3626 * @param apiVersion the api version
3627 * @throws AAIException the AAI exception
3629 public void validateNamedQuery(String transId, String fromAppId, String namedQueryUuid, String apiVersion )
3630 throws AAIException {
3632 // Note - this will throw an exception if the named query either can't be found, or if
3633 // we can't figure out its topology map.
3634 Vertex nqVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query",
3635 "named-query-uuid", namedQueryUuid);
3637 if( nqVtx == null ){
3638 String msg = " Could not find named-query with namedQueryUuid = [" + namedQueryUuid + "].";
3639 throw new AAIException("AAI_6114", msg);
3642 //Multimap<String, String> topoMap = genTopoMap4NamedQ( "junkTransId", "junkFromAppId",
3643 // graph, nqVtx, namedQueryUuid );
3644 //System.out.println("DEBUG -- for test only : --- ");
3645 //System.out.println("DEBUG -- topomap = [" + topoMap + "]");
3649 }// End validateNamedQuery()
3655 * @param resSet the res set
3656 * @param levelCount the level count
3658 public void showResultSet(ResultSet resSet, int levelCount ) {
3661 String propsStr = "";
3662 for( int i= 1; i <= levelCount; i++ ){
3663 propsStr = propsStr + "-";
3665 if( resSet.getVert() == null ){
3668 String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null);
3669 propsStr = propsStr + "[" + nt + "] ";
3671 //propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + resSet.getLocationInModelSubGraph();
3672 //propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]";
3673 propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph();
3675 Map<String,Object> overrideHash = resSet.getPropertyOverRideHash();
3676 if( overrideHash != null && !overrideHash.isEmpty() ){
3677 for( Map.Entry<String, Object> entry : overrideHash.entrySet() ){
3678 String propName = entry.getKey();
3679 Object propVal = entry.getValue();
3680 propsStr = propsStr + " [" + propName + " = " + propVal + "]";
3684 Iterator<VertexProperty<Object>> pI = resSet.getVert().properties();
3685 while( pI.hasNext() ){
3686 VertexProperty<Object> tp = pI.next();
3687 if( ! tp.key().startsWith("aai")
3688 && ! tp.key().equals("source-of-truth")
3689 //&& ! tp.key().equals("resource-version")
3690 && ! tp.key().startsWith("last-mod")
3693 propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]";
3697 // Show the "extra" lookup values too
3698 Map<String,Object> extraPropHash = resSet.getExtraPropertyHash();
3699 if( extraPropHash != null && !extraPropHash.isEmpty() ){
3700 for( Map.Entry<String, Object> entry : extraPropHash.entrySet() ){
3701 String propName = entry.getKey();
3702 Object propVal = entry.getValue();
3703 propsStr = propsStr + " [" + propName + " = " + propVal.toString() + "]";
3707 System.out.println( propsStr );
3708 LOGGER.info(propsStr);
3710 if( !resSet.getSubResultSet().isEmpty() ){
3711 ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator();
3712 while( listItr.hasNext() ){
3713 showResultSet( listItr.next(), levelCount );
3717 }// end of showResultSet()
3719 private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, String connectedNodeType) throws AAIUnknownObjectException, AAIException {
3720 QueryBuilder builder = this.engine.getQueryBuilder(startV).createEdgeTraversal(treeType, startV, loader.introspectorFromName(connectedNodeType));
3724 private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, String... connectedNodeType) throws AAIUnknownObjectException, AAIException {
3725 QueryBuilder[] builders = new QueryBuilder[connectedNodeType.length];
3726 for (int i = 0; i < connectedNodeType.length; i++) {
3727 builders[i] = this.engine.getQueryBuilder(startV).createEdgeTraversal(EdgeType.TREE, startV, loader.introspectorFromName(connectedNodeType[i]));
3729 QueryBuilder builder = this.engine.getQueryBuilder(startV).union(builders);
3733 private String addDBAliasedSuffix(String propName) {
3734 return propName + AAIProperties.DB_ALIAS_SUFFIX;
3737 protected String getPropNameWithAliasIfNeeded(String nodeType, String propName) throws AAIUnknownObjectException {
3739 String retPropName = propName;
3740 if( loader.introspectorFromName(nodeType).getPropertyMetadata(propName, PropertyMetadata.DB_ALIAS).isPresent() ){
3741 return propName + AAIProperties.DB_ALIAS_SUFFIX;