Merge "Update Sparky README files"
authorSteven Blimkie <Steven.Blimkie@amdocs.com>
Thu, 8 Feb 2018 14:54:11 +0000 (14:54 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 8 Feb 2018 14:54:11 +0000 (14:54 +0000)
47 files changed:
src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSynchronizer.java
src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizer.java
src/main/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizer.java
src/main/java/org/onap/aai/sparky/dal/elasticsearch/SearchAdapter.java
src/main/java/org/onap/aai/sparky/sync/AbstractEntitySynchronizer.java
src/main/java/org/onap/aai/sparky/util/NodeUtils.java
src/main/java/org/onap/aai/sparky/viewandinspect/services/BaseVisualizationContext.java
src/test/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizerTest.java [new file with mode: 0644]
src/test/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizerTest.java [new file with mode: 0644]
src/test/java/org/onap/aai/sparky/util/StringCollectionContainsMatcher.java [new file with mode: 0644]
src/test/java/org/onap/aai/sparky/viewandinspect/services/BaseVisualizationContextTest.java [new file with mode: 0644]
src/test/resources/filters/aaiui_filters_testConfig.json [new file with mode: 0644]
src/test/resources/filters/aaiui_views_testConfig.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/customer/customer-4.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-50.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-51.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-52.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-53.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-54.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-55.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-56.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-57.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-58.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-instance/service-instance-59.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/service-subscription/service-subscription-2.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-resources/tenant/tenant-1.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-50.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-51.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-52.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-53.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-54.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-55.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-56.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-57.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-58.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-59.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json [new file with mode: 0644]
src/test/resources/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json [new file with mode: 0644]
src/test/resources/sync/aai/activeInventory_generic-vnf_nodesQuery_response.json [new file with mode: 0644]
src/test/resources/sync/aai/activeInventory_service-subscription_nodesQuery_response.json [new file with mode: 0644]
src/test/resources/sync/aai/generic-vnf-generic-vnf-1_full_depth.json [new file with mode: 0644]
src/test/resources/sync/aai/generic-vnf-generic-vnf-2_full_depth.json [new file with mode: 0644]
src/test/resources/sync/aai/generic-vnf-generic-vnf-3_full_depth.json [new file with mode: 0644]
src/test/resources/sync/aai/service-subscription-service-subscription-1.json [new file with mode: 0644]
src/test/resources/sync/aai/service-subscription-service-subscription-2.json [new file with mode: 0644]
src/test/resources/sync/aai/service-subscription-service-subscription-3.json [new file with mode: 0644]

index 36cd8bc..3b02ff0 100644 (file)
@@ -176,9 +176,8 @@ public class AggregationSynchronizer extends AbstractEntitySynchronizer
             aaiWorkOnHand.decrementAndGet();
             processEntityTypeSelfLinks(typeLinksResult);
           } catch (Exception exc) {
-            // TODO -> LOG, what should be logged here?
-            
-            exc.printStackTrace();
+                 LOG.error(AaiUiMsgs.ERROR_GENERIC, "Processing execption while building working set.  Error:" 
+                       + exc.getMessage());
           }
 
           return null;
@@ -589,12 +588,15 @@ public class AggregationSynchronizer extends AbstractEntitySynchronizer
           }
         }
 
-     } catch (JsonProcessingException exc) {
-      // TODO -> LOG, waht should be logged here?
-    } catch (IOException exc) {
-      // TODO -> LOG, waht should be logged here?
-    }
-  }
+               } catch (JsonProcessingException exc) {
+                       LOG.error(AaiUiMsgs.ERROR_GENERIC,
+                                       "There was a JSON processing error fetching the elastic document for upsert.  Error: "
+                                                       + exc.getMessage());
+               } catch (IOException exc) {
+                       LOG.error(AaiUiMsgs.ERROR_GENERIC,
+                                       "There was an IO error fetching the elastic document for upsert.  Error: " + exc.getMessage());
+               }
+         }
   
   
   /**
@@ -622,6 +624,10 @@ public class AggregationSynchronizer extends AbstractEntitySynchronizer
   private void processEntityTypeSelfLinks(OperationResult operationResult) {
 
     JsonNode rootNode = null;
+    
+    if ( operationResult == null ) {
+       return;
+    }
 
     final String jsonResult = operationResult.getResult();
 
index 709842a..5172fe8 100644 (file)
@@ -143,6 +143,8 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
     this.syncInProgress = false;
     this.contextMap = MDC.getCopyOfContextMap();
     this.esPutExecutor = NodeUtils.createNamedExecutor("SUES-ES-PUT", 5, LOG);
+    this.retryQueue = new ConcurrentLinkedDeque<RetrySuggestionEntitySyncContainer>();
+    this.retryLimitTracker = new ConcurrentHashMap<String, Integer>();
     this.syncDurationInMs = -1;
     this.filtersConfig = filtersConfig;
   }
@@ -187,7 +189,9 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
               aaiWorkOnHand.decrementAndGet();
               processEntityTypeSelfLinks(typeLinksResult);
             } catch (Exception exc) {
-              // TODO -> LOG, what should be logged here?
+              LOG.error(AaiUiMsgs.ERROR_GENERIC,
+                  "An error occurred while processing entity self-links. Error: "
+                      + exc.getMessage());
             }
 
             return null;
@@ -228,7 +232,8 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
       retryLimitTracker.clear();
 
     } catch (Exception exc) {
-      // TODO -> LOG, waht should be logged here?
+      LOG.error(AaiUiMsgs.ERROR_GENERIC,
+          "An error occurred while performing the sync.  Error: " + exc.getMessage());
     }
 
     return OperationState.OK;
@@ -258,6 +263,10 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
   private void processEntityTypeSelfLinks(OperationResult operationResult) {
 
     JsonNode rootNode = null;
+    
+    if ( operationResult == null ) {
+       return;
+    }
 
     final String jsonResult = operationResult.getResult();
 
@@ -361,25 +370,38 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
   }
 
   /*
-   * Return a set of valid suggestion attributes for the provided entityName
-   * that are present in the JSON
+   * Return a set of valid suggestion attributes for the provided entityName that are present in the
+   * JSON
+   * 
    * @param node JSON node in which the attributes should be found
+   * 
    * @param entityName Name of the entity
+   * 
    * @return List of all valid suggestion attributes(key's)
    */
   public List<String> getSuggestableAttrNamesFromReponse(JsonNode node, String entityName) {
     List<String> suggestableAttr = new ArrayList<String>();
+
     HashMap<String, String> desc =
         suggestionEntityLookup.getSuggestionSearchEntityOxmModel().get(entityName);
-    String attr = desc.get("suggestibleAttributes");
-    suggestableAttr = Arrays.asList(attr.split(","));
-    List<String> suggestableValue = new ArrayList<>();
-    for (String attribute : suggestableAttr) {
-      if (node.get(attribute) != null && node.get(attribute).asText().length() > 0) {
-        suggestableValue.add(attribute);
+
+    if (desc != null) {
+
+      String attr = desc.get("suggestibleAttributes");
+
+      if (attr != null) {
+        suggestableAttr = Arrays.asList(attr.split(","));
+        List<String> suggestableValue = new ArrayList<String>();
+        for (String attribute : suggestableAttr) {
+          if (node.get(attribute) != null && node.get(attribute).asText().length() > 0) {
+            suggestableValue.add(attribute);
+          }
+        }
+        return suggestableValue;
       }
     }
-    return suggestableValue;
+
+    return new ArrayList<String>();
   }
 
   /**
@@ -454,9 +476,9 @@ public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
         }
       }
     } catch (JsonProcessingException exc) {
-      // TODO -> LOG, waht should be logged here?
+       LOG.error(AaiUiMsgs.ERROR_GENERIC, "There was a json processing error while processing the result from elasticsearch. Error: " + exc.getMessage());
     } catch (IOException exc) {
-      // TODO -> LOG, waht should be logged here?
+       LOG.error(AaiUiMsgs.ERROR_GENERIC, "There was a io processing error while processing the result from elasticsearch. Error: " + exc.getMessage());
     }
   }
 
index 0f0cce1..94a400b 100644 (file)
@@ -243,7 +243,8 @@ public class CrossEntityReferenceSynchronizer extends AbstractEntitySynchronizer
               aaiWorkOnHand.decrementAndGet();
               processEntityTypeSelfLinks(typeLinksResult);
             } catch (Exception exc) {
-              // TODO -> LOG, what should be logged here?
+              LOG.error(AaiUiMsgs.ERROR_GENERIC,
+                  "An error occurred processing entity selflinks. Error: " + exc.getMessage());
             }
 
             return null;
@@ -281,7 +282,9 @@ public class CrossEntityReferenceSynchronizer extends AbstractEntitySynchronizer
       retryLimitTracker.clear();
 
     } catch (Exception exc) {
-      // TODO -> LOG, waht should be logged here?
+      LOG.error(AaiUiMsgs.ERROR_GENERIC,
+          "An error occurred during entity synchronization. Error: " + exc.getMessage());
+
     }
 
     return OperationState.OK;
@@ -564,56 +567,57 @@ public class CrossEntityReferenceSynchronizer extends AbstractEntitySynchronizer
                                * link, this should be a permanent error
                                */
                               LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_SELFLINK_AMBIGUITY, String.valueOf(entityLinks.size()));
-                            } else {
-                              selfLink = ((JsonNode) entityLinks.toArray()[0]).asText();
-                              
-                              SearchableOxmEntityDescriptor searchableDescriptor = searchableEntityLookup.getSearchableEntityDescriptors().get( txn.getEntityType());
-                              
-                              if (searchableDescriptor != null && searchableDescriptor.getSearchableAttributes().size() > 0) {
-
-                                IndexableCrossEntityReference icer =
-                                    getPopulatedDocument(targetEntityInstance, cerDescriptor);
-
-                                for (String parentCrossEntityReferenceAttributeValue : extractedParentEntityAttributeValues) {
-                                  icer.addCrossEntityReferenceValue(
-                                      parentCrossEntityReferenceAttributeValue);
-                                }
-                                
-                                icer.setLink(ActiveInventoryAdapter.extractResourcePath(selfLink));
-
-                                icer.deriveFields();
-
-                                String link = null;
-                                try {
-                                  link = elasticSearchAdapter.buildElasticSearchGetDocUrl(getIndexName(), icer.getId());
-                                } catch (Exception exc) {
-                                  LOG.error(AaiUiMsgs.ES_FAILED_TO_CONSTRUCT_QUERY, exc.getLocalizedMessage());
-                                }
-
-                                if (link != null) {
-                                  NetworkTransaction n2 = new NetworkTransaction();
-                                  n2.setLink(link);
-                                  n2.setEntityType(txn.getEntityType());
-                                  n2.setDescriptor(txn.getDescriptor());
-                                  n2.setOperationType(HttpMethod.GET);
-
-                                  esWorkOnHand.incrementAndGet();
-
-                                  supplyAsync(new PerformElasticSearchRetrieval(n2, elasticSearchAdapter),
-                                      esExecutor).whenComplete((result, error) -> {
-
-                                        esWorkOnHand.decrementAndGet();
-
-                                        if (error != null) {
-                                          LOG.error(AaiUiMsgs.ES_RETRIEVAL_FAILED, error.getLocalizedMessage());
-                                        } else {
-                                          updateElasticSearchCounters(result);
-                                          performDocumentUpsert(result, icer);
-                                        }
-                                      });
-                                }
-                              }
+                          } else {
+                            selfLink = ((JsonNode) entityLinks.toArray()[0]).asText();
+
+
+                            IndexableCrossEntityReference icer =
+                                getPopulatedDocument(targetEntityInstance, cerDescriptor);
+
+                            for (String parentCrossEntityReferenceAttributeValue : extractedParentEntityAttributeValues) {
+                              icer.addCrossEntityReferenceValue(
+                                  parentCrossEntityReferenceAttributeValue);
+                            }
+
+                            icer.setLink(ActiveInventoryAdapter.extractResourcePath(selfLink));
+
+                            icer.deriveFields();
+
+                            String link = null;
+                            try {
+                              link = elasticSearchAdapter
+                                  .buildElasticSearchGetDocUrl(getIndexName(), icer.getId());
+                            } catch (Exception exc) {
+                              LOG.error(AaiUiMsgs.ES_FAILED_TO_CONSTRUCT_QUERY,
+                                  exc.getLocalizedMessage());
                             }
+
+                            if (link != null) {
+                              NetworkTransaction n2 = new NetworkTransaction();
+                              n2.setLink(link);
+                              n2.setEntityType(txn.getEntityType());
+                              n2.setDescriptor(txn.getDescriptor());
+                              n2.setOperationType(HttpMethod.GET);
+
+                              esWorkOnHand.incrementAndGet();
+
+                              supplyAsync(
+                                  new PerformElasticSearchRetrieval(n2, elasticSearchAdapter),
+                                  esExecutor).whenComplete((result, error) -> {
+
+                                    esWorkOnHand.decrementAndGet();
+
+                                    if (error != null) {
+                                      LOG.error(AaiUiMsgs.ES_RETRIEVAL_FAILED,
+                                          error.getLocalizedMessage());
+                                    } else {
+                                      updateElasticSearchCounters(result);
+                                      performDocumentUpsert(result, icer);
+                                    }
+                                  });
+                            }
+
+                          }
                           } else {
                             LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_DURING_AAI_RESPONSE_CONVERSION);
                           }
index c4e81b7..3abb54a 100644 (file)
@@ -37,7 +37,7 @@ import org.onap.aai.restclient.client.OperationResult;
 import org.onap.aai.restclient.client.RestClient;
 import org.onap.aai.sparky.dal.sas.config.SearchServiceConfig;
 import org.onap.aai.sparky.util.Encryptor;
-import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
+import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
 import org.slf4j.MDC;
 
 
@@ -63,9 +63,9 @@ public class SearchAdapter {
     Encryptor encryptor = new Encryptor();
 
     client = new RestClient().validateServerHostname(false).validateServerCertChain(false)
-        .clientCertFile(TierSupportUiConstants.CONFIG_AUTH_LOCATION + sasConfig.getCertName())
+        .clientCertFile(SparkyConstants.CONFIG_AUTH_LOCATION + sasConfig.getCertName())
         .clientCertPassword(encryptor.decryptValue(sasConfig.getKeystorePassword()))
-        .trustStore(TierSupportUiConstants.CONFIG_AUTH_LOCATION + sasConfig.getKeystore());
+        .trustStore(SparkyConstants.CONFIG_AUTH_LOCATION + sasConfig.getKeystore());
 
     commonHeaders = new HashMap<String, List<String>>();
     commonHeaders.put("Accept", Arrays.asList("application/json"));
index 298a493..bd55f3c 100644 (file)
@@ -407,16 +407,6 @@ public abstract class AbstractEntitySynchronizer {
     return -1;
   }
 
-  /**
-   * Update elastic search counters.
-   *
-   * @param method the method
-   * @param or the or
-   */
-  protected void updateElasticSearchCounters(HttpMethod method, OperationResult or) {
-    updateElasticSearchCounters(new NetworkTransaction(method, null, or));
-  }
-
   /**
    * Update elastic search counters.
    *
@@ -465,16 +455,6 @@ public abstract class AbstractEntitySynchronizer {
     }
   }
 
-  /**
-   * Update active inventory counters.
-   *
-   * @param method the method
-   * @param or the or
-   */
-  protected void updateActiveInventoryCounters(HttpMethod method, OperationResult or) {
-    updateActiveInventoryCounters(new NetworkTransaction(method, null, or));
-  }
-
   /**
    * Update active inventory counters.
    *
index 94c2b3e..7657d7e 100644 (file)
@@ -404,12 +404,12 @@ public class NodeUtils {
     String resourceId = null;
     if ("/".equals(link.substring(linkLength - 1))) {
       // Use-case:
-      // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS/
+      // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1/
       startIndex = link.lastIndexOf("/", linkLength - 2);
       resourceId = link.substring(startIndex + 1, linkLength - 1);
     } else {
       // Use-case:
-      // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS
+      // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1
       startIndex = link.lastIndexOf("/");
       resourceId = link.substring(startIndex + 1, linkLength);
     }
index 42e8d05..e5430af 100644 (file)
@@ -98,6 +98,7 @@ public class BaseVisualizationContext implements VisualizationContext {
   
   private ExecutorService aaiExecutorService;
   private OxmEntityLookup oxmEntityLookup;
+  private boolean rootNodeFound;
 
   /*
    * The node cache is intended to be a flat structure indexed by a primary key to avoid needlessly
@@ -137,8 +138,17 @@ public class BaseVisualizationContext implements VisualizationContext {
     this.mapper = new ObjectMapper();
     mapper.setSerializationInclusion(Include.NON_EMPTY);
     mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.KebabCaseStrategy());
+    this.rootNodeFound = false;
   }
   
+  protected boolean isRootNodeFound() {
+    return rootNodeFound;
+  }
+
+  protected void setRootNodeFound(boolean rootNodeFound) {
+    this.rootNodeFound = rootNodeFound;
+  }
+
   public long getContextId() {
     return contextId;
   }
@@ -351,7 +361,7 @@ public class BaseVisualizationContext implements VisualizationContext {
             aaiWorkOnHand.incrementAndGet();
             supplyAsync(new PerformSelfLinkDeterminationTask(txn, null, aaiAdapter),
                 aaiExecutorService).whenComplete((nodeTxn, error) -> {
-                  aaiWorkOnHand.decrementAndGet();
+                  
                   if (error != null) {
                     LOG.error(AaiUiMsgs.SELF_LINK_DETERMINATION_FAILED_GENERIC, selfLinkQuery);
                   } else {
@@ -435,6 +445,8 @@ public class BaseVisualizationContext implements VisualizationContext {
                     }
 
                   }
+                  
+                  aaiWorkOnHand.decrementAndGet();
 
                 });
 
@@ -671,7 +683,7 @@ public class BaseVisualizationContext implements VisualizationContext {
       supplyAsync(
           new PerformNodeSelfLinkProcessingTask(txn, depthModifier, aaiAdapter),
           aaiExecutorService).whenComplete((nodeTxn, error) -> {
-            aaiWorkOnHand.decrementAndGet();
+            
             if (error != null) {
 
               /*
@@ -729,6 +741,8 @@ public class BaseVisualizationContext implements VisualizationContext {
 
               }
             }
+            
+            aaiWorkOnHand.decrementAndGet();
 
           });
 
@@ -793,7 +807,11 @@ public class BaseVisualizationContext implements VisualizationContext {
    * @param queryParams the query params
    * @return true, if successful
    */
-  private boolean findAndMarkRootNode(QueryParams queryParams) {
+  private void findAndMarkRootNode(QueryParams queryParams) {
+
+    if (isRootNodeFound()) {
+      return;
+    }
 
     for (ActiveInventoryNode cacheNode : nodeCache.values()) {
 
@@ -801,12 +819,10 @@ public class BaseVisualizationContext implements VisualizationContext {
         cacheNode.setNodeDepth(0);
         cacheNode.setRootNode(true);
         LOG.info(AaiUiMsgs.ROOT_NODE_DISCOVERED, queryParams.getSearchTargetNodeId());
-        return true;
+        setRootNodeFound(true);
       }
     }
 
-    return false;
-
   }
 
   /**
@@ -814,14 +830,15 @@ public class BaseVisualizationContext implements VisualizationContext {
    *
    * @param rootNodeDiscovered the root node discovered
    */
-  private void processCurrentNodeStates(boolean rootNodeDiscovered) {
+  private void processCurrentNodeStates(QueryParams queryParams) {
     /*
      * Force an evaluation of node depths before determining if we should limit state-based
      * traversal or processing.
      */
-    if (rootNodeDiscovered) {
-      evaluateNodeDepths();
-    }
+    
+    findAndMarkRootNode(queryParams);
+    
+    verifyOutboundNeighbors();
 
     for (ActiveInventoryNode cacheNode : nodeCache.values()) {
 
@@ -861,16 +878,15 @@ public class BaseVisualizationContext implements VisualizationContext {
            * around the root node.
            */
           
-          if (!rootNodeDiscovered || cacheNode.getNodeDepth() < this.visualizationConfigs.getMaxSelfLinkTraversalDepth()) {
+          if (!isRootNodeFound() || cacheNode.getNodeDepth() < this.visualizationConfigs
+              .getMaxSelfLinkTraversalDepth()) {
 
             if (LOG.isDebugEnabled()) {
               LOG.debug(AaiUiMsgs.DEBUG_GENERIC, 
-                  "SLNC::processCurrentNodeState() -- Node at max depth,"
+                  "processCurrentNodeState() -- Node at max depth,"
                   + " halting processing at current state = -- "
                       + cacheNode.getState() + " nodeId = " + cacheNode.getNodeId());
             }
-
-            
             
             processNeighbors(cacheNode.getNodeId());
 
@@ -880,9 +896,6 @@ public class BaseVisualizationContext implements VisualizationContext {
         }
         default:
           break;
-
-
-
       }
 
     }
@@ -1347,10 +1360,13 @@ public class BaseVisualizationContext implements VisualizationContext {
      * always be equal to zero.
      */
 
-    if (queryParams.getSearchTargetNodeId().equals(newNode.getNodeId())) {
-      newNode.setNodeDepth(0);
-      newNode.setRootNode(true);
-      LOG.info(AaiUiMsgs.ROOT_NODE_DISCOVERED, queryParams.getSearchTargetNodeId());
+    if (!isRootNodeFound()) {
+      if (queryParams.getSearchTargetNodeId().equals(newNode.getNodeId())) {
+        newNode.setNodeDepth(0);
+        newNode.setRootNode(true);
+        LOG.info(AaiUiMsgs.ROOT_NODE_DISCOVERED, queryParams.getSearchTargetNodeId());
+        setRootNodeFound(true);
+      }
     }
 
     newNode.setSelfLink(searchTargetEntity.getLink());
@@ -1358,22 +1374,14 @@ public class BaseVisualizationContext implements VisualizationContext {
     nodeCache.putIfAbsent(newNode.getNodeId(), newNode);
   }
 
-  /**
-   * Checks for out standing work.
-   *
-   * @return true, if successful
-   */
-  private boolean hasOutStandingWork() {
-
+  private int getTotalWorkOnHand() {
+    
     int numNodesWithPendingStates = 0;
-
-    /*
-     * Force an evaluation of node depths before determining if we should limit state-based
-     * traversal or processing.
-     */
-
-    evaluateNodeDepths();
-
+    
+    if( isRootNodeFound()) {
+      evaluateNodeDepths();
+    }
+    
     for (ActiveInventoryNode n : nodeCache.values()) {
 
       switch (n.getState()) {
@@ -1410,9 +1418,39 @@ public class BaseVisualizationContext implements VisualizationContext {
 
     }
 
-    LOG.debug(AaiUiMsgs.OUTSTANDING_WORK_PENDING_NODES, String.valueOf(numNodesWithPendingStates));
+    LOG.debug(AaiUiMsgs.OUTSTANDING_WORK_PENDING_NODES,
+        String.valueOf(numNodesWithPendingStates));
 
-    return (numNodesWithPendingStates > 0);
+    int totalWorkOnHand = aaiWorkOnHand.get() + numNodesWithPendingStates;
+    
+    return totalWorkOnHand;
+    
+  }
+  
+  /**
+   * Checks for out standing work.
+   *
+   * @return true, if successful
+   */
+  private void processOutstandingWork(QueryParams queryParams) {
+    
+    while (getTotalWorkOnHand() > 0) {
+
+      /*
+       * Force an evaluation of node depths before determining if we should limit state-based
+       * traversal or processing.
+       */
+
+      processCurrentNodeStates(queryParams);
+
+      try {
+        Thread.sleep(10);
+      } catch (InterruptedException exc) {
+        LOG.error(AaiUiMsgs.PROCESSING_LOOP_INTERUPTED, exc.getMessage());
+        return;
+      }
+
+    }
 
   }
 
@@ -1424,70 +1462,26 @@ public class BaseVisualizationContext implements VisualizationContext {
 
     try {
 
+
       if (searchtargetEntity == null) {
         LOG.error(AaiUiMsgs.SELF_LINK_PROCESSING_ERROR, contextIdStr + " - Failed to"
             + " processSelfLinks, searchtargetEntity is null");
         return;
       }
 
-      processSearchableEntity(searchtargetEntity, queryParams);
-
       long startTimeInMs = System.currentTimeMillis();
 
-      /*
-       * wait until all transactions are complete or guard-timer expires.
-       */
-
-      long totalResolveTime = 0;
-      boolean hasOutstandingWork = hasOutStandingWork();
-      boolean outstandingWorkGuardTimerFired = false;
-      long maxGuardTimeInMs = 5000;
-      long guardTimeInMs = 0;
-      boolean foundRootNode = false;
-
+      processSearchableEntity(searchtargetEntity, queryParams);
       
       /*
-       * TODO:   Put a count-down-latch in place of the while loop, but if we do that then
-       * we'll need to decouple the visualization processing from the main thread so it can continue to process while
-       * the main thread is waiting on for count-down-latch gate to open.  This may also be easier once we move to the
-       * VisualizationService + VisualizationContext ideas. 
+       * This method is blocking until we decouple it with a CountDownLatch await condition,
+       * and make the internal graph processing more event-y.
        */
       
-      
-      while (hasOutstandingWork || !outstandingWorkGuardTimerFired) {
-
-        if (!foundRootNode) {
-          foundRootNode = findAndMarkRootNode(queryParams);
-        }
-
-        processCurrentNodeStates(foundRootNode);
-
-        verifyOutboundNeighbors();
-
-        try {
-          Thread.sleep(500);
-        } catch (InterruptedException exc) {
-          LOG.error(AaiUiMsgs.PROCESSING_LOOP_INTERUPTED, exc.getMessage());
-          return;
-        }
-
-        totalResolveTime = (System.currentTimeMillis() - startTimeInMs);
-
-        if (!hasOutstandingWork) {
-
-          guardTimeInMs += 500;
-
-          if (guardTimeInMs > maxGuardTimeInMs) {
-            outstandingWorkGuardTimerFired = true;
-          }
-        } else {
-          guardTimeInMs = 0;
-        }
-
-        hasOutstandingWork = hasOutStandingWork();
-
-      }
+      processOutstandingWork(queryParams);
 
+      long totalResolveTime = (System.currentTimeMillis() - startTimeInMs);
+      
       long opTime = System.currentTimeMillis() - startTimeInMs;
 
       LOG.info(AaiUiMsgs.ALL_TRANSACTIONS_RESOLVED, String.valueOf(totalResolveTime),
diff --git a/src/test/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizerTest.java b/src/test/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizerTest.java
new file mode 100644 (file)
index 0000000..038fe4b
--- /dev/null
@@ -0,0 +1,387 @@
+package org.onap.aai.sparky.autosuggestion.sync;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
+import org.onap.aai.sparky.config.oxm.OxmModelLoader;
+import org.onap.aai.sparky.config.oxm.OxmModelProcessor;
+import org.onap.aai.sparky.config.oxm.SuggestionEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.SuggestionEntityLookup;
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.search.filters.config.FiltersConfig;
+import org.onap.aai.sparky.search.filters.config.FiltersDetailsConfig;
+import org.onap.aai.sparky.search.filters.config.FiltersForViewsConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.util.TestResourceLoader;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class AutosuggestionSynchronizerTest {
+  
+  private static ObjectMapper mapper = new ObjectMapper();
+
+  private AutosuggestionSynchronizer suggestionSynchronizer;
+
+  private ElasticSearchSchemaConfig esSchemaConfig;
+  private NetworkStatisticsConfig aaiStatConfig;
+  private NetworkStatisticsConfig esStatConfig;
+  private OxmEntityLookup oxmEntityLookup;
+  private SuggestionEntityLookup suggestionEntityLookup;
+  private ElasticSearchAdapter esAdapter;
+  private ActiveInventoryAdapter aaiAdapter;
+
+
+  private FiltersConfig filtersConfig;
+
+
+
+  @Before
+  public void init() throws Exception {
+
+    esSchemaConfig = new ElasticSearchSchemaConfig();
+    esSchemaConfig.setIndexDocType("default");
+    esSchemaConfig.setIndexMappingsFileName(null);
+    esSchemaConfig.setIndexName("aggregation-index-name");
+    esSchemaConfig.setIndexSettingsFileName(null);
+
+
+    aaiStatConfig = new NetworkStatisticsConfig();
+
+    aaiStatConfig.setNumSamplesPerThreadForRunningAverage(100);
+
+    aaiStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
+    aaiStatConfig.setBytesHistogramMaxYAxis(1000000L);
+    aaiStatConfig.setBytesHistogramNumBins(20);
+    aaiStatConfig.setBytesHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
+    aaiStatConfig.setQueueLengthHistogramMaxYAxis(20000);
+    aaiStatConfig.setQueueLengthHistogramNumBins(20);
+    aaiStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
+    aaiStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
+    aaiStatConfig.setTaskAgeHistogramNumBins(20);
+    aaiStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
+    aaiStatConfig.setResponseTimeHistogramMaxYAxis(1000L);
+    aaiStatConfig.setResponseTimeHistogramNumBins(20);
+    aaiStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
+    aaiStatConfig.setTpsHistogramMaxYAxis(100);
+    aaiStatConfig.setTpsHistogramNumBins(20);
+    aaiStatConfig.setTpsHistogramNumDecimalPoints(2);
+
+    esStatConfig = new NetworkStatisticsConfig();
+
+    esStatConfig.setNumSamplesPerThreadForRunningAverage(100);
+
+    esStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
+    esStatConfig.setBytesHistogramMaxYAxis(1000000L);
+    esStatConfig.setBytesHistogramNumBins(20);
+    esStatConfig.setBytesHistogramNumDecimalPoints(2);
+
+    esStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
+    esStatConfig.setQueueLengthHistogramMaxYAxis(20000);
+    esStatConfig.setQueueLengthHistogramNumBins(20);
+    esStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
+
+    esStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
+    esStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
+    esStatConfig.setTaskAgeHistogramNumBins(20);
+    esStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
+
+    esStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
+    esStatConfig.setResponseTimeHistogramMaxYAxis(10000L);
+    esStatConfig.setResponseTimeHistogramNumBins(20);
+    esStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
+
+    esStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
+    esStatConfig.setTpsHistogramMaxYAxis(100);
+    esStatConfig.setTpsHistogramNumBins(20);
+    esStatConfig.setTpsHistogramNumDecimalPoints(2);
+
+    oxmEntityLookup = new OxmEntityLookup();
+
+    esAdapter = Mockito.mock(ElasticSearchAdapter.class);
+    aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
+
+
+    Set<OxmModelProcessor> processors = new HashSet<OxmModelProcessor>();
+
+    processors.add(oxmEntityLookup);
+
+
+
+    Map<String, OxmEntityDescriptor> oxmEntityDescriptors =
+        new HashMap<String, OxmEntityDescriptor>();
+
+    OxmEntityDescriptor genericVnfDescriptor = new OxmEntityDescriptor();
+    genericVnfDescriptor.setEntityName("generic-vnf");
+    List<String> pkeyNames = new ArrayList<String>();
+    pkeyNames.add("vnf-name");
+
+    genericVnfDescriptor.setPrimaryKeyAttributeNames(pkeyNames);
+
+    oxmEntityDescriptors.put("generic-vnf", genericVnfDescriptor);
+
+
+    oxmEntityLookup.setEntityDescriptors(oxmEntityDescriptors);
+
+
+    Map<String, SuggestionEntityDescriptor> suggestionEntityDescriptors =
+        new HashMap<String, SuggestionEntityDescriptor>();
+
+    SuggestionEntityDescriptor genericVnfSuggestionDescriptor = new SuggestionEntityDescriptor();
+    genericVnfSuggestionDescriptor.setEntityName("generic-vnf");
+    genericVnfSuggestionDescriptor.setPrimaryKeyAttributeNames(pkeyNames);
+
+    filtersConfig = new FiltersConfig(null, null);
+
+    FiltersDetailsConfig filtersDetailsConfig = mapper.readValue(
+        TestResourceLoader.getTestResourceDataJson("/filters/aaiui_filters_testConfig.json"),
+        FiltersDetailsConfig.class);
+    FiltersForViewsConfig filtersForViewsConfig = mapper.readValue(
+        TestResourceLoader.getTestResourceDataJson("/filters/aaiui_views_testConfig.json"),
+        FiltersForViewsConfig.class);
+
+    filtersConfig.setFiltersConfig(filtersDetailsConfig);
+    filtersConfig.setViewsConfig(filtersForViewsConfig);
+
+    /*
+     * SuggestionSearchEntity sse = new SuggestionSearchEntity(filtersConfig);
+     * 
+     * sse.setEntityType("generic-vnf"); sse.setSuggestionPropertyTypes( Arrays.asList("vnf-name"));
+     * 
+     * genericVnfSuggestionDescriptor.setSuggestionSearchEntity(sse);
+     * 
+     * suggestionEntityDescriptors.put("generic-vnf", genericVnfSuggestionDescriptor);
+     */
+
+    suggestionEntityLookup = new SuggestionEntityLookup(filtersConfig);
+
+    processors.add(suggestionEntityLookup);
+
+    OxmModelLoader oxmModelLoader = new OxmModelLoader(-1, processors);
+    oxmModelLoader.loadLatestOxmModel();
+
+    // suggestionEntityLookup.setSuggestionSearchEntityDescriptors(suggestionEntityDescriptors);
+  }
+
+  @Test
+  public void validateBasicConstruction() throws Exception {
+
+    suggestionSynchronizer = new AutosuggestionSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, oxmEntityLookup, suggestionEntityLookup, filtersConfig);
+
+    suggestionSynchronizer.setAaiAdapter(aaiAdapter);
+    suggestionSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    assertNotNull(suggestionSynchronizer.getAaiAdapter());
+    assertNotNull(suggestionSynchronizer.getElasticSearchAdapter());
+
+  }
+
+  @Test
+  public void validateSmallSync() throws Exception {
+
+    suggestionSynchronizer = new AutosuggestionSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, oxmEntityLookup, suggestionEntityLookup, filtersConfig);
+
+
+    suggestionSynchronizer.setAaiAdapter(aaiAdapter);
+    suggestionSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    String nodesQueryResponse = TestResourceLoader
+        .getTestResourceDataJson("/sync/aai/activeInventory_generic-vnf_nodesQuery_response.json");
+
+    OperationResult genericVnfSelfLinks = new OperationResult();
+
+    genericVnfSelfLinks.setResultCode(200);
+    genericVnfSelfLinks.setResult(nodesQueryResponse);
+
+    Mockito.when(aaiAdapter.getSelfLinksByEntityType("generic-vnf"))
+        .thenReturn(genericVnfSelfLinks);
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-1"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-1");
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-2"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-2");
+
+    Mockito
+        .when(
+            aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-3"), Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-3");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("generic-vnf-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/generic-vnf-generic-vnf-1_full_depth.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("generic-vnf-2"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/generic-vnf-generic-vnf-2_full_depth.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("generic-vnf-3"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/generic-vnf-generic-vnf-3_full_depth.json")));
+
+    Mockito.when(esAdapter.buildElasticSearchGetDocUrl(Mockito.anyString(), Mockito.anyString()))
+        .thenReturn("http://localhost:9200/myindex/mytype/doc1",
+            "http://localhost:9200/myindex/mytype/doc2",
+            "http://localhost:9200/myindex/mytype/doc3");
+
+    /*
+     * Our initial gets from elastic search should be record-not-found
+     */
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc1"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc2"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc3"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+
+
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+        .thenReturn(new OperationResult(200, null));
+
+    OperationState syncState = suggestionSynchronizer.doSync();
+    assertEquals(OperationState.OK, syncState);
+
+    assertNotNull(suggestionSynchronizer.getStatReport(false));
+    assertNotNull(suggestionSynchronizer.getStatReport(true));
+
+    suggestionSynchronizer.clearCache();
+    suggestionSynchronizer.shutdown();
+
+
+  }
+
+  @Test
+  public void validateSmallSyncWithRetries() throws Exception {
+
+    suggestionSynchronizer = new AutosuggestionSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, oxmEntityLookup, suggestionEntityLookup, filtersConfig);
+
+
+    suggestionSynchronizer.setAaiAdapter(aaiAdapter);
+    suggestionSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    String nodesQueryResponse = TestResourceLoader
+        .getTestResourceDataJson("/sync/aai/activeInventory_generic-vnf_nodesQuery_response.json");
+
+    OperationResult genericVnfSelfLinks = new OperationResult();
+
+    genericVnfSelfLinks.setResultCode(200);
+    genericVnfSelfLinks.setResult(nodesQueryResponse);
+
+    Mockito.when(aaiAdapter.getSelfLinksByEntityType("generic-vnf"))
+        .thenReturn(genericVnfSelfLinks);
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-1"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-1");
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-2"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-2");
+
+    Mockito
+        .when(
+            aaiAdapter.repairSelfLink(Matchers.contains("generic-vnf-3"), Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-3");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("generic-vnf-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/generic-vnf-generic-vnf-1_full_depth.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("generic-vnf-2"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/generic-vnf-generic-vnf-2_full_depth.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("generic-vnf-3"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/generic-vnf-generic-vnf-3_full_depth.json")));
+
+    Mockito.when(esAdapter.buildElasticSearchGetDocUrl(Mockito.anyString(), Mockito.anyString()))
+        .thenReturn("http://localhost:9200/myindex/mytype/doc1",
+            "http://localhost:9200/myindex/mytype/doc2",
+            "http://localhost:9200/myindex/mytype/doc3");
+
+    /*
+     * Our initial gets from elastic search should be record-not-found
+     */
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc1"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc2"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc3"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+
+
+    /*
+     * Elastic Search puts always fail with a version conflict = 409
+     */
+
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+        .thenReturn(new OperationResult(409, null));
+
+    OperationState syncState = suggestionSynchronizer.doSync();
+    assertEquals(OperationState.OK, syncState);
+
+    assertNotNull(suggestionSynchronizer.getStatReport(false));
+    assertNotNull(suggestionSynchronizer.getStatReport(true));
+
+    suggestionSynchronizer.clearCache();
+    suggestionSynchronizer.shutdown();
+
+
+  }
+}
diff --git a/src/test/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizerTest.java b/src/test/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizerTest.java
new file mode 100644 (file)
index 0000000..c6c999a
--- /dev/null
@@ -0,0 +1,1035 @@
+package org.onap.aai.sparky.crossentityreference.sync;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.config.oxm.CrossEntityReferenceLookup;
+import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
+import org.onap.aai.sparky.config.oxm.OxmModelLoader;
+import org.onap.aai.sparky.config.oxm.OxmModelProcessor;
+import org.onap.aai.sparky.config.oxm.SearchableEntityLookup;
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.util.StringCollectionContainsMatcher;
+import org.onap.aai.sparky.util.TestResourceLoader;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class CrossEntityReferenceSynchronizerTest {
+  
+  private static ObjectMapper mapper = new ObjectMapper();
+
+  private CrossEntityReferenceSynchronizer cerSynchronizer;
+
+  private ElasticSearchSchemaConfig esSchemaConfig;
+  private NetworkStatisticsConfig aaiStatConfig;
+  private NetworkStatisticsConfig esStatConfig;
+  private OxmEntityLookup oxmEntityLookup;
+  private SearchableEntityLookup searchableEntityLookup;
+  private ElasticSearchAdapter esAdapter;
+  private ActiveInventoryAdapter aaiAdapter;
+  private CrossEntityReferenceLookup cerLookup;
+  private RestEndpointConfig aaiRestEndPointConfig;
+
+  @Before
+  public void init() throws Exception {
+
+    esSchemaConfig = new ElasticSearchSchemaConfig();
+    esSchemaConfig.setIndexDocType("default");
+    esSchemaConfig.setIndexMappingsFileName(null);
+    esSchemaConfig.setIndexName("aggregation-index-name");
+    esSchemaConfig.setIndexSettingsFileName(null);
+
+
+    aaiStatConfig = new NetworkStatisticsConfig();
+
+    aaiStatConfig.setNumSamplesPerThreadForRunningAverage(100);
+
+    aaiStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
+    aaiStatConfig.setBytesHistogramMaxYAxis(1000000L);
+    aaiStatConfig.setBytesHistogramNumBins(20);
+    aaiStatConfig.setBytesHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
+    aaiStatConfig.setQueueLengthHistogramMaxYAxis(20000);
+    aaiStatConfig.setQueueLengthHistogramNumBins(20);
+    aaiStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
+    aaiStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
+    aaiStatConfig.setTaskAgeHistogramNumBins(20);
+    aaiStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
+    aaiStatConfig.setResponseTimeHistogramMaxYAxis(1000L);
+    aaiStatConfig.setResponseTimeHistogramNumBins(20);
+    aaiStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
+
+    aaiStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
+    aaiStatConfig.setTpsHistogramMaxYAxis(100);
+    aaiStatConfig.setTpsHistogramNumBins(20);
+    aaiStatConfig.setTpsHistogramNumDecimalPoints(2);
+
+    esStatConfig = new NetworkStatisticsConfig();
+
+    esStatConfig.setNumSamplesPerThreadForRunningAverage(100);
+
+    esStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
+    esStatConfig.setBytesHistogramMaxYAxis(1000000L);
+    esStatConfig.setBytesHistogramNumBins(20);
+    esStatConfig.setBytesHistogramNumDecimalPoints(2);
+
+    esStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
+    esStatConfig.setQueueLengthHistogramMaxYAxis(20000);
+    esStatConfig.setQueueLengthHistogramNumBins(20);
+    esStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
+
+    esStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
+    esStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
+    esStatConfig.setTaskAgeHistogramNumBins(20);
+    esStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
+
+    esStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
+    esStatConfig.setResponseTimeHistogramMaxYAxis(10000L);
+    esStatConfig.setResponseTimeHistogramNumBins(20);
+    esStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
+
+    esStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
+    esStatConfig.setTpsHistogramMaxYAxis(100);
+    esStatConfig.setTpsHistogramNumBins(20);
+    esStatConfig.setTpsHistogramNumDecimalPoints(2);
+
+    oxmEntityLookup = new OxmEntityLookup();
+
+    esAdapter = Mockito.mock(ElasticSearchAdapter.class);
+    aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
+
+
+    Set<OxmModelProcessor> processors = new HashSet<OxmModelProcessor>();
+
+    processors.add(oxmEntityLookup);
+
+
+    Map<String, OxmEntityDescriptor> oxmEntityDescriptors =
+        new HashMap<String, OxmEntityDescriptor>();
+
+    OxmEntityDescriptor genericVnfDescriptor = new OxmEntityDescriptor();
+    genericVnfDescriptor.setEntityName("generic-vnf");
+    List<String> pkeyNames = new ArrayList<String>();
+    pkeyNames.add("vnf-name");
+
+    genericVnfDescriptor.setPrimaryKeyAttributeNames(pkeyNames);
+
+    oxmEntityDescriptors.put("generic-vnf", genericVnfDescriptor);
+
+
+    oxmEntityLookup.setEntityDescriptors(oxmEntityDescriptors);
+
+    cerLookup = new CrossEntityReferenceLookup();
+    processors.add(cerLookup);
+    
+    searchableEntityLookup = new SearchableEntityLookup();
+    processors.add(searchableEntityLookup);
+    
+    OxmModelLoader oxmModelLoader = new OxmModelLoader(-1, processors);
+    oxmModelLoader.loadLatestOxmModel();
+
+    aaiRestEndPointConfig = new RestEndpointConfig();
+    aaiRestEndPointConfig.setNumRequestRetries(5);
+    
+    Mockito.when(aaiAdapter.getEndpointConfig()).thenReturn(aaiRestEndPointConfig);
+    
+  }
+
+  @Test
+  public void validateBasicConstruction() throws Exception {
+
+    cerSynchronizer = new CrossEntityReferenceSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, cerLookup, oxmEntityLookup, searchableEntityLookup);
+    
+    cerSynchronizer.setAaiAdapter(aaiAdapter);
+    cerSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    assertNotNull(cerSynchronizer.getAaiAdapter());
+    assertNotNull(cerSynchronizer.getElasticSearchAdapter());
+
+  }
+  
+  private Matcher<List<String>> listContainsValue(String expectedValue) {
+    return new StringCollectionContainsMatcher(expectedValue);
+  }
+
+  @Test
+  public void validateSmallSync() throws Exception {
+
+    cerSynchronizer = new CrossEntityReferenceSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, cerLookup, oxmEntityLookup, searchableEntityLookup);
+
+    cerSynchronizer.setAaiAdapter(aaiAdapter);
+    cerSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    String nodesQueryResponse = TestResourceLoader
+        .getTestResourceDataJson("/sync/aai/activeInventory_service-subscription_nodesQuery_response.json");
+
+    OperationResult entitySelfLinks = new OperationResult();
+
+    entitySelfLinks.setResultCode(200);
+    entitySelfLinks.setResult(nodesQueryResponse);
+
+    Mockito.when(aaiAdapter.getSelfLinksByEntityType("service-subscription"))
+        .thenReturn(entitySelfLinks);
+    
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-1"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1");
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-2"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2");
+
+    Mockito
+        .when(
+            aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-3"), Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-3/service-subscriptions/service-subscription/service-subscription-3");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-2"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-2.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-1.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("service-subscription-3"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/service-subscription-service-subscription-3.json")));
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-59"))))
+        .thenReturn("https://server.proxy:8443/aai/v11/search/generic-query/service-instance-59");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-54"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-54");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-55"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-55");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-50"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-50");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-52"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-52");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-57"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-57");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-53"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-53");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-58"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-58");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-51"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-51");
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-56"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-56");
+    
+    
+    
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-59"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-59.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-54"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-54.json")));
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-55"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-55.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-50"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-50.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-52"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-52.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-57"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-57.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-53"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-53.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-58"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-58.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-51"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-51.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-56"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-56.json")));
+
+    
+    
+    
+    
+    
+    /*
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-59"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-59.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-54"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-54.json")));
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-55"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-55.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-50"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-50.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-52"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-52.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-57"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-57.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-53"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-53.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-58"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-58.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-51"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-51.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-56"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-56.json")));
+
+    
+    */
+    
+    
+    
+    
+    Mockito.when(esAdapter.buildElasticSearchGetDocUrl(Mockito.anyString(), Mockito.anyString()))
+        .thenReturn("http://localhost:9200/myindex/mytype/doc1",
+            "http://localhost:9200/myindex/mytype/doc2",
+            "http://localhost:9200/myindex/mytype/doc3");
+
+    /*
+     * Our initial gets from elastic search should be record-not-found
+     */
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc1"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc2"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc3"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+
+
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+        .thenReturn(new OperationResult(200, null));
+
+    OperationState syncState = cerSynchronizer.doSync();
+    assertEquals(OperationState.OK, syncState);
+
+    assertNotNull(cerSynchronizer.getStatReport(false));
+    assertNotNull(cerSynchronizer.getStatReport(true));
+
+    cerSynchronizer.clearCache();
+    cerSynchronizer.shutdown();
+
+
+  }
+
+  @Test
+  public void validateSmallSyncWithRetries() throws Exception {
+
+    cerSynchronizer = new CrossEntityReferenceSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, cerLookup, oxmEntityLookup, searchableEntityLookup);
+
+    cerSynchronizer.setAaiAdapter(aaiAdapter);
+    cerSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    String nodesQueryResponse = TestResourceLoader
+        .getTestResourceDataJson("/sync/aai/activeInventory_service-subscription_nodesQuery_response.json");
+
+    OperationResult entitySelfLinks = new OperationResult();
+
+    entitySelfLinks.setResultCode(200);
+    entitySelfLinks.setResult(nodesQueryResponse);
+
+    Mockito.when(aaiAdapter.getSelfLinksByEntityType("service-subscription"))
+        .thenReturn(entitySelfLinks);
+    
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-1"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1");
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-2"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2");
+
+    Mockito
+        .when(
+            aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-3"), Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-3/service-subscriptions/service-subscription/service-subscription-3");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-2"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-2.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-1.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("service-subscription-3"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/service-subscription-service-subscription-3.json")));
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-59"))))
+        .thenReturn("https://server.proxy:8443/aai/v11/search/generic-query/service-instance-59");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-54"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-54");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-55"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-55");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-50"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-50");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-52"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-52");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-57"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-57");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-53"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-53");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-58"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-58");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-51"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-51");
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-56"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-56");
+    
+    
+    
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-59"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-59.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-54"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-54.json")));
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-55"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-55.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-50"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-50.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-52"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-52.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-57"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-57.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-53"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-53.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-58"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-58.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-51"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-51.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-56"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-56.json")));
+
+    
+    
+    
+    
+    
+    /*
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-59"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-59.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-54"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-54.json")));
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-55"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-55.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-50"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-50.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-52"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-52.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-57"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-57.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-53"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-53.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-58"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-58.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-51"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-51.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("service-instance-56"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-resources/service-instance/service-instance-56.json")));
+
+    
+    */
+    
+    
+    
+    
+    Mockito.when(esAdapter.buildElasticSearchGetDocUrl(Mockito.anyString(), Mockito.anyString()))
+        .thenReturn("http://localhost:9200/myindex/mytype/doc1",
+            "http://localhost:9200/myindex/mytype/doc2",
+            "http://localhost:9200/myindex/mytype/doc3");
+
+    /*
+     * Our initial gets from elastic search should be record-not-found
+     */
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc1"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc2"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc3"), Mockito.any()))
+        .thenReturn(new OperationResult(404, null));
+
+
+    /*
+     * Cause version conflict errors on every put to test retry flow
+     */
+    
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+        .thenReturn(new OperationResult(409, null));
+
+    OperationState syncState = cerSynchronizer.doSync();
+    assertEquals(OperationState.OK, syncState);
+
+    assertNotNull(cerSynchronizer.getStatReport(false));
+    assertNotNull(cerSynchronizer.getStatReport(true));
+
+    cerSynchronizer.clearCache();
+    cerSynchronizer.shutdown();
+
+
+
+
+  }
+  
+  
+  
+  @Test
+  public void validateSmallSyncWithEntityMerges() throws Exception {
+
+    cerSynchronizer = new CrossEntityReferenceSynchronizer(esSchemaConfig, 5, 5, 5, aaiStatConfig,
+        esStatConfig, cerLookup, oxmEntityLookup, searchableEntityLookup);
+
+    cerSynchronizer.setAaiAdapter(aaiAdapter);
+    cerSynchronizer.setElasticSearchAdapter(esAdapter);
+
+    String nodesQueryResponse = TestResourceLoader
+        .getTestResourceDataJson("/sync/aai/activeInventory_service-subscription_nodesQuery_response.json");
+
+    OperationResult entitySelfLinks = new OperationResult();
+
+    entitySelfLinks.setResultCode(200);
+    entitySelfLinks.setResult(nodesQueryResponse);
+
+    Mockito.when(aaiAdapter.getSelfLinksByEntityType("service-subscription"))
+        .thenReturn(entitySelfLinks);
+    
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-1"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1");
+
+    Mockito
+        .when(aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-2"),
+            Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2");
+
+    Mockito
+        .when(
+            aaiAdapter.repairSelfLink(Matchers.contains("service-subscription-3"), Mockito.anyString()))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/business/customers/customer/customer-3/service-subscriptions/service-subscription/service-subscription-3");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-2"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-2.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("service-subscription-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/service-subscription-service-subscription-1.json")));
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(Matchers.contains("service-subscription-3"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/service-subscription-service-subscription-3.json")));
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-59"))))
+        .thenReturn("https://server.proxy:8443/aai/v11/search/generic-query/service-instance-59");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-54"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-54");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-55"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-55");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-50"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-50");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-52"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-52");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-57"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-57");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-53"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-53");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-58"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-58");
+
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-51"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-51");
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(listContainsValue("service-instance-56"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-56");
+    
+    
+    
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-59"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-59.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-54"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-54.json")));
+    
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-55"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-55.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-50"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-50.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-52"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-52.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-57"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-57.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-53"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-53.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-58"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-58.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-51"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-51.json")));
+
+    Mockito
+    .when(aaiAdapter.queryActiveInventoryWithRetries(
+        Matchers.contains("generic-query/service-instance-56"), Mockito.anyString(),
+        Mockito.anyInt()))
+    .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+        "/sync/aai/aai-traversal/generic-query/service-instance-56.json")));
+
+    
+    Mockito.when(esAdapter.buildElasticSearchGetDocUrl(Mockito.anyString(), Mockito.anyString()))
+        .thenReturn("http://localhost:9200/myindex/mytype/doc1",
+            "http://localhost:9200/myindex/mytype/doc2",
+            "http://localhost:9200/myindex/mytype/doc3");
+
+    /*
+     * Our initial gets from elastic search return 200 ok with a found entity document requiring a doc update
+     */
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc1"), Mockito.any())).thenReturn(new OperationResult(200,
+            TestResourceLoader.getTestResourceDataJson("/sync/ElasticSearch/docEntityFromElasticSearch1.json")));
+
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc2"), Mockito.any())).thenReturn(new OperationResult(200,
+            TestResourceLoader.getTestResourceDataJson("/sync/ElasticSearch/docEntityFromElasticSearch2.json")));
+
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc3"), Mockito.any())).thenReturn(new OperationResult(200,
+            TestResourceLoader.getTestResourceDataJson("/sync/ElasticSearch/docEntityFromElasticSearch3.json")));
+
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc4"), Mockito.any())).thenReturn(new OperationResult(200,
+            TestResourceLoader.getTestResourceDataJson("/sync/ElasticSearch/docEntityFromElasticSearch4.json")));
+
+    Mockito.when(esAdapter.doGet(Matchers.contains("doc5"), Mockito.any())).thenReturn(new OperationResult(200,
+            TestResourceLoader.getTestResourceDataJson("/sync/ElasticSearch/docEntityFromElasticSearch5.json")));
+
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+            .thenReturn(new OperationResult(200, null));
+    
+
+    
+    Mockito.when(esAdapter.doPut(Matchers.contains("doc"), Mockito.any(), Mockito.any()))
+        .thenReturn(new OperationResult(200, null));
+
+    OperationState syncState = cerSynchronizer.doSync();
+    assertEquals(OperationState.OK, syncState);
+
+    assertNotNull(cerSynchronizer.getStatReport(false));
+    assertNotNull(cerSynchronizer.getStatReport(true));
+
+    cerSynchronizer.clearCache();
+    cerSynchronizer.shutdown();
+
+
+
+
+  }
+  
+  
+  
+  
+}
diff --git a/src/test/java/org/onap/aai/sparky/util/StringCollectionContainsMatcher.java b/src/test/java/org/onap/aai/sparky/util/StringCollectionContainsMatcher.java
new file mode 100644 (file)
index 0000000..e8b3258
--- /dev/null
@@ -0,0 +1,39 @@
+package org.onap.aai.sparky.util;
+
+import java.util.List;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+
+public class StringCollectionContainsMatcher extends BaseMatcher<List<String>> {
+
+  private String valueToCheck;
+  
+  @SuppressWarnings({"unused", "unchecked"})
+  public StringCollectionContainsMatcher(String valToCheck) {
+    this.valueToCheck = valToCheck;
+  }
+  
+  @Override
+  public boolean matches(Object arg0) {
+
+    @SuppressWarnings("unchecked")
+    List<String> argumentList = (List<String>) arg0;
+    
+    for ( String listItem : argumentList ) {
+      
+      if ( listItem.contains(valueToCheck)) {
+        return true;
+      }
+    }
+    
+    return false;
+  }
+
+  @Override
+  public void describeTo(Description arg0) {
+    // TODO Auto-generated method stub
+    
+  }
+  
+}
diff --git a/src/test/java/org/onap/aai/sparky/viewandinspect/services/BaseVisualizationContextTest.java b/src/test/java/org/onap/aai/sparky/viewandinspect/services/BaseVisualizationContextTest.java
new file mode 100644 (file)
index 0000000..09ca3a3
--- /dev/null
@@ -0,0 +1,273 @@
+package org.onap.aai.sparky.viewandinspect.services;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.cl.mdc.MdcContext;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
+import org.onap.aai.sparky.config.oxm.OxmModelLoader;
+import org.onap.aai.sparky.config.oxm.OxmModelProcessor;
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig;
+import org.onap.aai.sparky.sync.entity.SearchableEntity;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.onap.aai.sparky.util.StringCollectionContainsMatcher;
+import org.onap.aai.sparky.util.TestResourceLoader;
+import org.onap.aai.sparky.viewandinspect.config.VisualizationConfigs;
+import org.onap.aai.sparky.viewandinspect.entity.ActiveInventoryNode;
+import org.onap.aai.sparky.viewandinspect.entity.QueryParams;
+import org.onap.aai.sparky.viewandinspect.enumeration.NodeProcessingState;
+
+
+public class BaseVisualizationContextTest {
+  
+  private static SecureRandom secureRandom = new SecureRandom();
+  private static Logger LOG = LoggerFactory.getInstance().getLogger(BaseVisualizationContextTest.class);
+
+  private BaseVisualizationContext baseVisualizationContext;
+  private ExecutorService aaiExecutorService;
+  private VisualizationConfigs visualizationConfig;
+
+  private OxmEntityLookup oxmEntityLookup;
+  
+  private ActiveInventoryAdapter aaiAdapter;
+  private RestEndpointConfig aaiRestEndPointConfig;
+
+  @Before
+  public void init() throws Exception {
+
+    aaiExecutorService = NodeUtils.createNamedExecutor("SLNC-WORKER", 5, LOG);
+    visualizationConfig = new VisualizationConfigs();
+    
+    ArrayList<String> shallowEntities = new ArrayList<String>();
+    shallowEntities.add("cloud-region");
+    
+    visualizationConfig.setShallowEntities(shallowEntities);
+    visualizationConfig.setMaxSelfLinkTraversalDepth(2);
+    oxmEntityLookup = new OxmEntityLookup();
+
+    aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
+
+
+    Set<OxmModelProcessor> processors = new HashSet<OxmModelProcessor>();
+
+    processors.add(oxmEntityLookup);
+
+     
+    OxmModelLoader oxmModelLoader = new OxmModelLoader(-1, processors);
+    oxmModelLoader.loadLatestOxmModel();
+
+    aaiRestEndPointConfig = new RestEndpointConfig();
+    aaiRestEndPointConfig.setNumRequestRetries(5);
+    
+    Mockito.when(aaiAdapter.getEndpointConfig()).thenReturn(aaiRestEndPointConfig);
+    
+    MdcContext.initialize("" + secureRandom.nextLong(), "AAI-UI", "", "partner-name",
+        "localhost:4242");
+    
+    // all our resources are prefixed already, so the repairSelfLink shouldn't do anything to the link
+    Mockito.when(aaiAdapter.repairSelfLink(Matchers.contains(""))).thenReturn("");
+
+    
+  }
+  
+  private Matcher<List<String>> listContainsValue(String expectedValue) {
+    return new StringCollectionContainsMatcher(expectedValue);
+  }
+
+
+  @Test
+  public void validateBasicConstruction() throws Exception {
+
+    long contextId = secureRandom.nextLong();
+    
+    baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
+        aaiExecutorService, visualizationConfig, oxmEntityLookup);
+    
+    assertEquals(contextId, baseVisualizationContext.getContextId());
+
+  }
+  
+  @Test
+  public void validateSmallGraphAssembly() throws Exception {
+
+    /**
+     * We have a tiny graph that we will validate assembly of:
+     * 
+     * <li>customer -> tenant
+     * <li>customer -> service-subscription
+     * <li>service-subscription -> service-instance-1
+     * <li>service-subscription -> service-instance-2
+     * 
+     * At the end of this success path, we should have 5 nodes in the node cache. Once we have this
+     * flow we can experiment with error paths involving resource download failures to ensure graph
+     * nodes are in the correct state and that expected nodes are successfully represented in the
+     * cache.
+     */
+
+    long contextId = secureRandom.nextLong();
+
+    baseVisualizationContext = new BaseVisualizationContext(contextId, aaiAdapter,
+        aaiExecutorService, visualizationConfig, oxmEntityLookup);
+
+    SearchableEntity searchableEntity = new SearchableEntity();
+    String customerSelfLink =
+        "https://server.proxy:8443/aai/v11/business/customers/customer/customer-4";
+    String customerNodeId = NodeUtils.generateUniqueShaDigest(customerSelfLink);
+
+    searchableEntity.setId(customerNodeId);
+    searchableEntity.setEntityType("customer");
+    searchableEntity.setEntityPrimaryKeyValue("customer-4");
+    searchableEntity.setLink(customerSelfLink);
+
+    QueryParams queryParams = new QueryParams();
+    queryParams.setSearchTargetNodeId(customerNodeId);
+    queryParams.setSearchTargetPrimaryKeyValues("customer-4");
+
+    //  aai customer resource dip
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("customer-4"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/aai-resources/customer/customer-4.json")));
+
+    //  aai tenant resource dip
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("tenant/tenant-1"), Mockito.anyString(),
+            Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/aai-resources/tenant/tenant-1.json")));
+    
+    // generic-queries for service-subscription
+    
+    Mockito
+    .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-subscription"),
+        Matchers.argThat(listContainsValue("service-subscription.service-type:service-subscription-2"))))
+    .thenReturn(
+        "https://server.proxy:8443/aai/v11/search/generic-query/service-subscription-2");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers.contains("generic-query/service-subscription-2"), Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader
+            .getTestResourceDataJson("/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json")));    
+    
+    // generic-queries for service-instance-1
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(
+                listContainsValue("service-instance-id:service-instance-54"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-54");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers
+                .contains("generic-query/service-instance-id/service-instance-54"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json")));
+
+    // generic-queries for service-instance-2
+    
+    Mockito
+        .when(aaiAdapter.getGenericQueryForSelfLink(Matchers.contains("service-instance"),
+            Matchers.argThat(
+                listContainsValue("service-instance-id:service-instance-55"))))
+        .thenReturn(
+            "https://server.proxy:8443/aai/v11/search/generic-query/service-instance-id/service-instance-55");
+
+    Mockito
+        .when(aaiAdapter.queryActiveInventoryWithRetries(
+            Matchers
+                .contains("generic-query/service-instance-id/service-instance-55"),
+            Mockito.anyString(), Mockito.anyInt()))
+        .thenReturn(new OperationResult(200, TestResourceLoader.getTestResourceDataJson(
+            "/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json")));    
+    
+    
+    
+    // start the test
+    
+    baseVisualizationContext.processSelfLinks(searchableEntity, queryParams);
+
+    /*
+     * validation can be in the form of validating nodes + relationships from the node cache
+     * baseVisualizationContext.getNodeCache();
+     */
+
+    Map<String, ActiveInventoryNode> nodeCache = baseVisualizationContext.getNodeCache();
+
+    assertEquals(5, nodeCache.size());
+    assertNotNull(nodeCache.get(customerNodeId));
+    assertEquals("customer", nodeCache.get(customerNodeId).getEntityType());
+    
+    // verify node collection nodes
+    
+    ActiveInventoryNode customerNode = nodeCache.get("da4101ad19b3c380a1c12ffeda8ab390e1489fb4a22a392c9a1939db63c3dec5");
+    ActiveInventoryNode ssNode = nodeCache.get("f4ceaf19459993c4fc9438a7579dd20d786109f4455e38682c579045b7ae615e");
+    ActiveInventoryNode tenantNode = nodeCache.get("4735439b29e446b339535668238076e4b392eaa3eec218936e12f735179bc55e");
+    ActiveInventoryNode s1 = nodeCache.get("f975ab453b142197af5d0173e0a9cf2aa22d10502f8ad655c8d17de81b066e8f");
+    ActiveInventoryNode s2 = nodeCache.get("de77ef8f76dd6f19662b163527ff839891b9596cac655e3143fdd7ad39e2e4e3");
+    
+    assertNotNull( customerNode );
+    assertNotNull( ssNode );
+    assertNotNull( tenantNode );
+    assertNotNull( s1 );
+    assertNotNull( s2 );
+    
+    // verify node depths
+    
+    assertEquals( 0, customerNode.getNodeDepth() );
+    assertEquals( 1, ssNode.getNodeDepth() );
+    
+    /*
+     * I think there is a bug in the way the node depth is represented due to the enforcement of
+     * bidirectional links being disabled. We may have to circle back to this behavior at some point
+     * and re-verify that the behavior works properly.
+     */
+    
+    assertEquals( 2, tenantNode.getNodeDepth() );
+    assertEquals( 2, s1.getNodeDepth() );
+    assertEquals( 2, s2.getNodeDepth() );
+
+    // verify node states
+    
+    assertEquals( NodeProcessingState.READY, customerNode.getState() );
+    assertEquals( NodeProcessingState.READY, ssNode.getState() );
+    
+    /*
+     * these nodes have a NEIGHBORS_UNPROCESSED state because the max traversal depth was hit before
+     * processing all the nested relationships.  I think what we should look at is advancing the state
+     * to READY if in fact there are no relationships to process, which I think could be the case
+     * sometimes.
+     */
+    assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, tenantNode.getState() );
+    assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, s1.getState() );
+    assertEquals( NodeProcessingState.NEIGHBORS_UNPROCESSED, s2.getState() );
+
+  }  
+  
+}
diff --git a/src/test/resources/filters/aaiui_filters_testConfig.json b/src/test/resources/filters/aaiui_filters_testConfig.json
new file mode 100644 (file)
index 0000000..62b6811
--- /dev/null
@@ -0,0 +1,79 @@
+{
+       "filters": [
+       {
+               "filterId": "1",
+               "filterName": "Orchestration-Status",
+               "displayName": "Orchestration Status",
+               "dataType": "dropDown",
+        "multiSelect": "false",
+        "watermark": "Any Orchestration Status",
+        "optionsType": "options",
+               "dataSource": {
+                       "indexName": "aggregate_generic-vnf_index",
+                       "docType": "default",
+                       "fieldName": "orchestration-status"
+               }
+       },
+       {
+               "filterId": "2",
+               "filterName": "Prov-Status",
+               "displayName": "Provisioning Status",
+               "dataType": "dropDown",
+        "multiSelect": "false",
+        "watermark": "Any Provisioning Status",
+        "optionsType": "options",
+               "dataSource": {
+                       "indexName": "aggregate_generic-vnf_index",
+                       "docType": "default",
+                       "fieldName": "prov-status"
+               }
+       },
+       {
+               "filterId": "5",
+               "filterName": "Date",
+               "displayName": "Date",
+               "dataType": "date",
+        "multiSelect": "false",
+        "watermark": "Choose Date Range",
+        "defaultValue" : {"decode": "Today", "code": "last_0_hours"},
+        "optionsType": "dynamicOptions",
+        "optionsValues": [
+               {"decode": "Today", "code": "last_0_hours"},
+               {"decode": "Since Yesterday", "code": "last_1_days"},
+               {"decode": "Since Last Week", "code": "last_1_weeks"},
+               {"decode": "Since Last Month", "code": "last_1_months"},
+               {"decode": "Since Last Year", "code": "last_1_years"},
+               {"decode": "Custom Range", "code": "custom_range"}
+        ]
+       },
+    {
+        "filterId": "7",
+               "filterName": "NF-Type",
+               "displayName": "Network Function Type",
+               "dataType": "dropDown",
+        "multiSelect": "false",
+        "watermark": "Any Network Function Type",
+        "optionsType": "options",
+               "dataSource": {
+                       "indexName": "aggregate_generic-vnf_index",
+                       "docType": "default",
+                       "fieldName": "nf-type"
+               }    
+       },
+    {
+        "filterId": "8",
+               "filterName": "NF-Role",
+               "displayName": "Network Function Role",
+               "dataType": "dropDown",
+        "multiSelect": "false",
+        "watermark": "Any Network Function Role",
+        "optionsType": "options",
+               "dataSource": {
+                       "indexName": "aggregate_generic-vnf_index",
+                       "docType": "default",
+                       "fieldName": "nf-role"
+               }    
+       }       
+       
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/filters/aaiui_views_testConfig.json b/src/test/resources/filters/aaiui_views_testConfig.json
new file mode 100644 (file)
index 0000000..9ca0119
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "views": [
+    {
+        "viewName" : "vnfSearch",
+        "filters" : [
+          {
+             "filterId": "1"
+          },
+          {
+             "filterId": "2"
+          },
+          {
+             "filterId": "7"
+          },
+          {
+             "filterId": "8"
+          }
+         ]
+    }
+   ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/customer/customer-4.json b/src/test/resources/sync/aai/aai-resources/customer/customer-4.json
new file mode 100644 (file)
index 0000000..df805ba
--- /dev/null
@@ -0,0 +1,60 @@
+{
+    "global-customer-id": "customer-4",
+    "subscriber-name": "Gold",
+    "subscriber-type": "GoldType",
+    "resource-version": "1494001938080",
+    "service-subscriptions": {
+        "service-subscription": [
+            {
+                "service-type": "service-subscription-2",
+                "resource-version": "1494001891362",
+                "service-instances": {
+                    "service-instance": [
+                        {
+                            "service-instance-id": "service-instance-54",
+                            "service-instance-name": "si_failtest",
+                            "model-invariant-id": "732263bd-0655-428d-a347-d65676d1a949",
+                            "resource-version": "1494001997513"
+                        },
+                        {
+                            "service-instance-id": "service-instance-55",
+                            "service-instance-name": "test-343432",
+                            "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+                            "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+                            "resource-version": "1500370094198",
+                            "orchestration-status": "Active"
+                        }
+                    ]
+                },
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "tenant",
+                            "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/tenant-1",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "cloud-region.cloud-owner",
+                                    "relationship-value": "cotton-candy"
+                                },
+                                {
+                                    "relationship-key": "cloud-region.cloud-region-id",
+                                    "relationship-value": "fluffy-clouds"
+                                },
+                                {
+                                    "relationship-key": "tenant.tenant-id",
+                                    "relationship-value": "tenant-1"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "tenant.tenant-name",
+                                    "property-value": "CandyMan"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-50.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-50.json
new file mode 100644 (file)
index 0000000..17a48fc
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "service-instance-id": "service-instance-50",
+    "service-instance-name": "s01",
+    "service-type": "",
+    "service-role": "",
+    "environment-context": "Universe",
+    "workload-context": "QuantumContext",
+    "model-invariant-id": "5b9c0f33-eec1-484a-bf77-736a6644d7a8",
+    "model-version-id": "b75e0d22-05ff-4448-9266-5f0d4e1dbbd6",
+    "resource-version": "1510659038818",
+    "orchestration-status": "Active",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "project",
+                "related-link": "/aai/v11/business/projects/project/project1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "project.project-name",
+                        "relationship-value": "project1"
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-51.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-51.json
new file mode 100644 (file)
index 0000000..bfc5241
--- /dev/null
@@ -0,0 +1,28 @@
+{
+    "service-instance-id": "service-instance-51",
+    "service-instance-name": "test765445g",
+    "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+    "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+    "resource-version": "1499868690949",
+    "orchestration-status": "Active",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "generic-vnf",
+                "related-link": "/aai/v11/network/generic-vnfs/generic-vnf/fbb52a16-2c57-4212-802f-32dbba2204f2",
+                "relationship-data": [
+                    {
+                        "relationship-key": "generic-vnf.vnf-id",
+                        "relationship-value": "fbb52a16-2c57-4212-802f-32dbba2204f2"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "generic-vnf.vnf-name",
+                        "property-value": "fdfdfdf"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-52.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-52.json
new file mode 100644 (file)
index 0000000..6083a8f
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "service-instance-id": "service-instance-52",
+    "service-instance-name": "si52",
+    "service-type": "",
+    "service-role": "",
+    "environment-context": "null",
+    "workload-context": "null",
+    "model-invariant-id": "d7b48529-6ae2-49f0-8633-b29e7cd4d4ce",
+    "model-version-id": "44671b15-83dd-4db7-a36e-dfada3eaa2f9",
+    "resource-version": "1508144995828",
+    "orchestration-status": "Active"
+}
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-53.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-53.json
new file mode 100644 (file)
index 0000000..5765c43
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "service-instance-id": "service-instance-53",
+    "service-instance-name": "a1",
+    "service-type": "si53-type",
+    "service-role": "si53-role",
+    "environment-context": "Universe",
+    "workload-context": "Nano",
+    "model-invariant-id": "340f3957-ff0a-4503-866d-a34fd1b97450",
+    "model-version-id": "ee2d8783-8495-4fb1-9553-6cdbd2dd3a50",
+    "resource-version": "1509355912484",
+    "orchestration-status": "Active",
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-54.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-54.json
new file mode 100644 (file)
index 0000000..249c38b
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "service-instance-id": "service-instance-54",
+    "service-instance-name": "si_failtest",
+    "model-invariant-id": "732263bd-0655-428d-a347-d65676d1a949",
+    "resource-version": "1494001997513"
+}
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-55.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-55.json
new file mode 100644 (file)
index 0000000..8db5b2e
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "service-instance-id": "service-instance-55",
+    "service-instance-name": "test-343432",
+    "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+    "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+    "resource-version": "1500370094198",
+    "orchestration-status": "Active"
+}
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-56.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-56.json
new file mode 100644 (file)
index 0000000..a87de6f
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "service-instance-id": "service-instance-56",
+    "resource-version": "1495736709053"
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-57.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-57.json
new file mode 100644 (file)
index 0000000..ce26fda
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "service-instance-id": "service-instance-57",
+    "service-instance-name": "first_macro_shani",
+    "service-type": "",
+    "service-role": "",
+    "workload-context": "Universe",
+    "model-invariant-id": "5b9c0f33-eec1-484a-bf77-736a6644d7a8",
+    "model-version-id": "b75e0d22-05ff-4448-9266-5f0d4e1dbbd6",
+    "resource-version": "1508071197869",
+    "orchestration-status": "Active"
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-58.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-58.json
new file mode 100644 (file)
index 0000000..7e6f5e9
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    "service-instance-id": "service-instance-58",
+    "service-instance-name": "a3",
+    "service-type": "",
+    "service-role": "",
+    "environment-context": "FluffyClouds",
+    "workload-context": "TasteGood",
+    "model-invariant-id": "d5937aa1-37fb-4ed0-8c30-5144b89a64ae",
+    "model-version-id": "06ac9663-54cf-4c77-b926-6e8757cf6380",
+    "resource-version": "1509356358573",
+    "orchestration-status": "Active",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "generic-vnf",
+                "related-link": "/aai/v11/network/generic-vnfs/generic-vnf/9c925d7e-1a94-4784-a45b-408c8cc96fa8",
+                "relationship-data": [
+                    {
+                        "relationship-key": "generic-vnf.vnf-id",
+                        "relationship-value": "9c925d7e-1a94-4784-a45b-408c8cc96fa8"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "generic-vnf.vnf-name",
+                        "property-value": "dfdsfds"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-59.json b/src/test/resources/sync/aai/aai-resources/service-instance/service-instance-59.json
new file mode 100644 (file)
index 0000000..37e7d35
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "service-instance-id": "service-instance-59",
+    "resource-version": "1506087955081"
+}
diff --git a/src/test/resources/sync/aai/aai-resources/service-subscription/service-subscription-2.json b/src/test/resources/sync/aai/aai-resources/service-subscription/service-subscription-2.json
new file mode 100644 (file)
index 0000000..2d02ccc
--- /dev/null
@@ -0,0 +1,50 @@
+{
+    "service-type": "service-subscription-2",
+    "resource-version": "1494001891362",
+    "service-instances": {
+        "service-instance": [
+            {
+                "service-instance-id": "service-instance-54",
+                "service-instance-name": "si_failtest",
+                "model-invariant-id": "732263bd-0655-428d-a347-d65676d1a949",
+                "resource-version": "1494001997513"
+            },
+            {
+                "service-instance-id": "service-instance-55",
+                "service-instance-name": "test-343432",
+                "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+                "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+                "resource-version": "1500370094198",
+                "orchestration-status": "Active"
+            }
+        ]
+    },
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/myCloud/isBig/tenants/tenant/tenant-1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "myCloud"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "isBig"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "tenant-1"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "SuperDude"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-resources/tenant/tenant-1.json b/src/test/resources/sync/aai/aai-resources/tenant/tenant-1.json
new file mode 100644 (file)
index 0000000..3dad086
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "tenant-id": "tenant-1",
+    "tenant-name": "SuperDude",
+    "resource-version": "1494001855362",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "service-subscription",
+                "related-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2",
+                "relationship-data": [
+                    {
+                        "relationship-key": "customer.global-customer-id",
+                        "relationship-value": "customer-4"
+                    },
+                    {
+                        "relationship-key": "service-subscription.service-type",
+                        "relationship-value": "service-subscription-2"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-50.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-50.json
new file mode 100644 (file)
index 0000000..d4e9d8d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-50"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-51.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-51.json
new file mode 100644 (file)
index 0000000..7c29652
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-51"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-52.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-52.json
new file mode 100644 (file)
index 0000000..5d88946
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-52"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-53.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-53.json
new file mode 100644 (file)
index 0000000..8422ab0
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-53"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-54.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-54.json
new file mode 100644 (file)
index 0000000..d61ee8e
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-54"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-55.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-55.json
new file mode 100644 (file)
index 0000000..7594913
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-55"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-56.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-56.json
new file mode 100644 (file)
index 0000000..dc66079
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/DHV_20170525142406/service-subscriptions/service-subscription/uCPE/service-instances/service-instance/service-instance-56"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-57.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-57.json
new file mode 100644 (file)
index 0000000..427fbdf
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-57"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-58.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-58.json
new file mode 100644 (file)
index 0000000..f459422
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-58"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-59.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance-59.json
new file mode 100644 (file)
index 0000000..380f932
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1/service-instances/service-instance/service-instance-59"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-54.json
new file mode 100644 (file)
index 0000000..d61ee8e
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-54"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-instance/service-instance-55.json
new file mode 100644 (file)
index 0000000..7594913
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-instance",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2/service-instances/service-instance/service-instance-55"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json b/src/test/resources/sync/aai/aai-traversal/generic-query/service-subscription/service-subscription-2.json
new file mode 100644 (file)
index 0000000..d377d5d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-subscription",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/activeInventory_generic-vnf_nodesQuery_response.json b/src/test/resources/sync/aai/activeInventory_generic-vnf_nodesQuery_response.json
new file mode 100644 (file)
index 0000000..f1cb3d4
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "result-data": [
+        {
+            "resource-type": "generic-vnf",
+            "resource-link": "/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-1"
+        },
+        {
+            "resource-type": "generic-vnf",
+            "resource-link": "/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-2"
+        },
+        {
+            "resource-type": "generic-vnf",
+            "resource-link": "/aai/v11/network/generic-vnfs/generic-vnf/generic-vnf-3"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/activeInventory_service-subscription_nodesQuery_response.json b/src/test/resources/sync/aai/activeInventory_service-subscription_nodesQuery_response.json
new file mode 100644 (file)
index 0000000..414724f
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "result-data": [
+        {
+            "resource-type": "service-subscription",
+            "resource-link": "/aai/v11/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription1"
+        },
+        {
+            "resource-type": "service-subscription",
+            "resource-link": "/aai/v11/business/customers/customer/customer-2/service-subscriptions/service-subscription/service-subscription-2"
+        },
+        {
+            "resource-type": "service-subscription",
+            "resource-link": "/aai/v11/business/customers/customer/customer-3/service-subscriptions/service-subscription/service-subscription-3"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/generic-vnf-generic-vnf-1_full_depth.json b/src/test/resources/sync/aai/generic-vnf-generic-vnf-1_full_depth.json
new file mode 100644 (file)
index 0000000..14abe18
--- /dev/null
@@ -0,0 +1,136 @@
+{
+    "vnf-id": "generic-vnf-1",
+    "vnf-name": "vProbe_Fe_VEPMS_sk316t_sd_01",
+    "vnf-type": "vProbe Fe VEPMS_sk316t/vProbe Fe VEPMS_sk316t 0",
+    "service-id": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
+    "prov-status": "PREPROV",
+    "orchestration-status": "Created",
+    "in-maint": false,
+    "is-closed-loop-disabled": false,
+    "resource-version": "1511102454640",
+    "model-invariant-id": "b8dba4bd-04ee-42bc-8c41-db06addb6866",
+    "model-version-id": "c9e7826d-c4b8-40c7-83e4-d9f96e7d5827",
+    "model-customization-id": "d2ca6d16-6529-4362-b53e-7bf4141372b1",
+    "nf-type": "PROBES",
+    "nf-function": "vProbes (Frontend )",
+    "nf-role": "vLB",
+    "nf-naming-code": "null",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "service-instance",
+                "related-link": "/aai/v11/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Mobility/service-instances/service-instance/22663785-ebb9-49c7-b95b-209537e6627f",
+                "relationship-data": [
+                    {
+                        "relationship-key": "customer.global-customer-id",
+                        "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"
+                    },
+                    {
+                        "relationship-key": "service-subscription.service-type",
+                        "relationship-value": "Mobility"
+                    },
+                    {
+                        "relationship-key": "service-instance.service-instance-id",
+                        "relationship-value": "22663785-ebb9-49c7-b95b-209537e6627f"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "service-instance.service-instance-name",
+                        "property-value": "vProbe_Fe_VEPMS_sk316t_sd"
+                    }
+                ]
+            },
+            {
+                "related-to": "line-of-business",
+                "related-link": "/aai/v11/business/lines-of-business/line-of-business/lob1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "line-of-business.line-of-business-name",
+                        "relationship-value": "lob1"
+                    }
+                ]
+            },
+            {
+                "related-to": "platform",
+                "related-link": "/aai/v11/business/platforms/platform/platform1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "platform.platform-name",
+                        "relationship-value": "platform1"
+                    }
+                ]
+            },
+            {
+                "related-to": "volume-group",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/volume-groups/volume-group/ecf748d5-be43-45ae-a8b1-c8520d144bdf",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "volume-group.volume-group-id",
+                        "relationship-value": "ecf748d5-be43-45ae-a8b1-c8520d144bdf"
+                    }
+                ]
+            },
+            {
+                "related-to": "volume-group",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/volume-groups/volume-group/1e26c1a7-8a91-4459-ba02-8cc2d70dd065",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "volume-group.volume-group-id",
+                        "relationship-value": "1e26c1a7-8a91-4459-ba02-8cc2d70dd065"
+                    }
+                ]
+            },
+            {
+                "related-to": "volume-group",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/volume-groups/volume-group/5223cfdc-50bf-4607-9651-2270384d6414",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "volume-group.volume-group-id",
+                        "relationship-value": "5223cfdc-50bf-4607-9651-2270384d6414"
+                    }
+                ]
+            }
+        ]
+    },
+    "vf-modules": {
+        "vf-module": [
+            {
+                "vf-module-id": "eba81b96-851e-4374-9b9e-d186527f3c46",
+                "vf-module-name": "zmtn6afprb01_base1_sd_02",
+                "heat-stack-id": "zmtn6afprb01_base1_sd_02/cfd1203d-ff2f-49a3-a40b-72ac67cd8432",
+                "orchestration-status": "active",
+                "is-base-vf-module": true,
+                "resource-version": "1511301104226",
+                "model-invariant-id": "c01b5b9f-0760-4bcc-93b5-e1b24dd9bcfa",
+                "model-version-id": "30e71b66-93c6-4e0f-b7ff-de26b45c83e9",
+                "model-customization-id": "caaf8b40-03e9-4c58-9d18-613f564e2ea8",
+                "module-index": 0
+            }
+        ]
+    }
+}
diff --git a/src/test/resources/sync/aai/generic-vnf-generic-vnf-2_full_depth.json b/src/test/resources/sync/aai/generic-vnf-generic-vnf-2_full_depth.json
new file mode 100644 (file)
index 0000000..a03e4c8
--- /dev/null
@@ -0,0 +1,118 @@
+{
+    "vnf-id": "generic-vnf-2",
+    "vnf-name": "zmtn6apndns_v6_01",
+    "vnf-type": "APNDNS_mm779p_II/APNDNS_mm779p_II 0",
+    "service-id": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
+    "prov-status": "PREPROV",
+    "orchestration-status": "Created",
+    "in-maint": false,
+    "is-closed-loop-disabled": false,
+    "resource-version": "1511184323962",
+    "model-invariant-id": "f3f6ed00-cd41-4e96-b669-0daa10da5491",
+    "model-version-id": "f76e6281-d80f-4403-9603-4245b0c8d8cd",
+    "model-customization-id": "f499ebb9-4383-42c1-8ace-2b682f312504",
+    "nf-type": "DNS",
+    "nf-function": "APN-DNS",
+    "nf-role": "VDNS",
+    "nf-naming-code": "null",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "service-instance",
+                "related-link": "/aai/v11/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Nimbus/service-instances/service-instance/3a743f07-86cc-47db-bee5-03fa91c77748",
+                "relationship-data": [
+                    {
+                        "relationship-key": "customer.global-customer-id",
+                        "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"
+                    },
+                    {
+                        "relationship-key": "service-subscription.service-type",
+                        "relationship-value": "Nimbus"
+                    },
+                    {
+                        "relationship-key": "service-instance.service-instance-id",
+                        "relationship-value": "3a743f07-86cc-47db-bee5-03fa91c77748"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "service-instance.service-instance-name",
+                        "property-value": "APNDNS_mm779p_II_V6"
+                    }
+                ]
+            },
+            {
+                "related-to": "line-of-business",
+                "related-link": "/aai/v11/business/lines-of-business/line-of-business/lob1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "line-of-business.line-of-business-name",
+                        "relationship-value": "lob1"
+                    }
+                ]
+            },
+            {
+                "related-to": "platform",
+                "related-link": "/aai/v11/business/platforms/platform/platform1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "platform.platform-name",
+                        "relationship-value": "platform1"
+                    }
+                ]
+            },
+            {
+                "related-to": "volume-group",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/volume-groups/volume-group/03ec51a4-2ea9-4947-b66a-b01c7b9e9ea5",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "volume-group.volume-group-id",
+                        "relationship-value": "03ec51a4-2ea9-4947-b66a-b01c7b9e9ea5"
+                    }
+                ]
+            },
+            {
+                "related-to": "volume-group",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/volume-groups/volume-group/1b3bf4c2-a4cc-4c37-afcc-ec49f5c1c653",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "volume-group.volume-group-id",
+                        "relationship-value": "1b3bf4c2-a4cc-4c37-afcc-ec49f5c1c653"
+                    }
+                ]
+            }
+        ]
+    },
+    "vf-modules": {
+        "vf-module": [
+            {
+                "vf-module-id": "1b5602c0-b0c7-42fd-9bbd-8d503e464c5a",
+                "vf-module-name": "APNDNS_V6_base",
+                "heat-stack-id": "APNDNS_V6_base/bd3aa649-179f-4017-a848-f9a90cfa8908",
+                "orchestration-status": "active",
+                "is-base-vf-module": true,
+                "resource-version": "1511271087769",
+                "model-invariant-id": "874a259a-c4a3-4928-bbaa-0cd391ea3ec8",
+                "model-version-id": "417a7a36-87f8-4366-8d7b-95e47f1009b9",
+                "model-customization-id": "76a64957-74c7-4598-84c9-aa0e94bd2a69",
+                "module-index": 0
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/generic-vnf-generic-vnf-3_full_depth.json b/src/test/resources/sync/aai/generic-vnf-generic-vnf-3_full_depth.json
new file mode 100644 (file)
index 0000000..de2481b
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    "vnf-id": "generic-vnf-3",
+    "vnf-name": "generic-vnf-test01-name19",
+    "vnf-name2": "generic-vnf-test01-name19",
+    "vnf-type": "generic-vnf-rx2202-type",
+    "service-id": "d0217510-514b-429d-9b84-e4ed74e4c552",
+    "regional-resource-zone": "example-regional-resource-zone-val-8204",
+    "prov-status": "ACTIVE",
+    "license-key": "lk",
+    "equipment-role": "role",
+    "orchestration-status": "PendingDelete",
+    "heat-stack-id": "generic-vnf-rx2202-heat-stack-id",
+    "mso-catalog-key": "generic-vnf-rx2202-mso-catalog-key",
+    "management-option": "generic-vnf-rx2202-management-option",
+    "ipv4-oam-address": "1.2.3.4",
+    "ipv4-loopback0-address": "4.5.6.7",
+    "nm-lan-v6-address": "33::34",
+    "management-v6-address": "34::35",
+    "vcpu": 7957,
+    "vcpu-units": "example-vcpu-units-val-8204",
+    "vmemory": 168,
+    "vmemory-units": "example-vmemory-units-val-8204",
+    "vdisk": 3227,
+    "vdisk-units": "example-vdisk-units-val-8204",
+    "in-maint": false,
+    "is-closed-loop-disabled": true,
+    "resource-version": "1500476417001",
+    "nf-type": "vCE/vFW",
+    "nf-role": "vSeGW"
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/service-subscription-service-subscription-1.json b/src/test/resources/sync/aai/service-subscription-service-subscription-1.json
new file mode 100644 (file)
index 0000000..3d2d38c
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "service-type": "service-subscription-1",
+    "resource-version": "1506087955078",
+    "service-instances": {
+        "service-instance": [
+            {
+                "service-instance-id": "service-subscription-1",
+                "resource-version": "1506087955081"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/service-subscription-service-subscription-2.json b/src/test/resources/sync/aai/service-subscription-service-subscription-2.json
new file mode 100644 (file)
index 0000000..d4c2414
--- /dev/null
@@ -0,0 +1,350 @@
+{
+    "service-type": "service-subscription-2",
+    "resource-version": "1494001891362",
+    "service-instances": {
+        "service-instance": [
+            {
+                "service-instance-id": "service-instance-54",
+                "service-instance-name": "si_failtest",
+                "model-invariant-id": "732263bd-0655-428d-a347-d65676d1a949",
+                "resource-version": "1494001997513"
+            },
+            {
+                "service-instance-id": "service-instance-55",
+                "service-instance-name": "test-343432",
+                "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+                "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+                "resource-version": "1500370094198",
+                "orchestration-status": "Active"
+            },
+            {
+                "service-instance-id": "service-instance-50",
+                "service-instance-name": "s01",
+                "service-type": "",
+                "service-role": "",
+                "environment-context": "General_Revenue-Bearing",
+                "workload-context": "Production",
+                "model-invariant-id": "5b9c0f33-eec1-484a-bf77-736a6644d7a8",
+                "model-version-id": "b75e0d22-05ff-4448-9266-5f0d4e1dbbd6",
+                "resource-version": "1510659038818",
+                "orchestration-status": "Active",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "project",
+                            "related-link": "/aai/v11/business/projects/project/project1",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "project.project-name",
+                                    "relationship-value": "project1"
+                                }
+                            ]
+                        },
+                        {
+                            "related-to": "owning-entity",
+                            "related-link": "/aai/v11/business/owning-entities/owning-entity/589fe0db-26c4-45e5-9f4e-a246c74fce76",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "owning-entity.owning-entity-id",
+                                    "relationship-value": "589fe0db-26c4-45e5-9f4e-a246c74fce76"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            },
+            {
+                "service-instance-id": "service-instance-52",
+                "service-instance-name": "shanitest",
+                "service-type": "",
+                "service-role": "",
+                "environment-context": "null",
+                "workload-context": "null",
+                "model-invariant-id": "d7b48529-6ae2-49f0-8633-b29e7cd4d4ce",
+                "model-version-id": "44671b15-83dd-4db7-a36e-dfada3eaa2f9",
+                "resource-version": "1508144995828",
+                "orchestration-status": "Active"
+            },
+            {
+                "service-instance-id": "service-instance-57",
+                "service-instance-name": "first_macro_shani",
+                "service-type": "",
+                "service-role": "",
+                "environment-context": "General_Revenue-Bearing",
+                "workload-context": "Production",
+                "model-invariant-id": "5b9c0f33-eec1-484a-bf77-736a6644d7a8",
+                "model-version-id": "b75e0d22-05ff-4448-9266-5f0d4e1dbbd6",
+                "resource-version": "1508071197869",
+                "orchestration-status": "Active"
+            },
+            {
+                "service-instance-id": "service-instance-53",
+                "service-instance-name": "a1",
+                "service-type": "service_type_shani",
+                "service-role": "service_role_shani",
+                "environment-context": "General_Revenue-Bearing",
+                "workload-context": "Production",
+                "model-invariant-id": "340f3957-ff0a-4503-866d-a34fd1b97450",
+                "model-version-id": "ee2d8783-8495-4fb1-9553-6cdbd2dd3a50",
+                "resource-version": "1509355912484",
+                "orchestration-status": "Active",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "owning-entity",
+                            "related-link": "/aai/v11/business/owning-entities/owning-entity/2356a43d-ed56-43b6-aefc-8391b82588c9",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "owning-entity.owning-entity-id",
+                                    "relationship-value": "2356a43d-ed56-43b6-aefc-8391b82588c9"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            },
+            {
+                "service-instance-id": "service-instance-58",
+                "service-instance-name": "a3",
+                "service-type": "",
+                "service-role": "",
+                "environment-context": "General_Revenue-Bearing",
+                "workload-context": "Production",
+                "model-invariant-id": "d5937aa1-37fb-4ed0-8c30-5144b89a64ae",
+                "model-version-id": "06ac9663-54cf-4c77-b926-6e8757cf6380",
+                "resource-version": "1509356358573",
+                "orchestration-status": "Active",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "generic-vnf",
+                            "related-link": "/aai/v11/network/generic-vnfs/generic-vnf/9c925d7e-1a94-4784-a45b-408c8cc96fa8",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "generic-vnf.vnf-id",
+                                    "relationship-value": "9c925d7e-1a94-4784-a45b-408c8cc96fa8"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "generic-vnf.vnf-name",
+                                    "property-value": "dfdsfds"
+                                }
+                            ]
+                        },
+                        {
+                            "related-to": "owning-entity",
+                            "related-link": "/aai/v11/business/owning-entities/owning-entity/589fe0db-26c4-45e5-9f4e-a246c74fce76",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "owning-entity.owning-entity-id",
+                                    "relationship-value": "589fe0db-26c4-45e5-9f4e-a246c74fce76"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            },
+            {
+                "service-instance-id": "service-instance-51",
+                "service-instance-name": "test765445g",
+                "model-invariant-id": "709d1be4-9a3f-4a29-8c4d-a20465e808a3",
+                "model-version-id": "240376de-870e-48df-915a-31f140eedd2c",
+                "resource-version": "1499868690949",
+                "orchestration-status": "Active",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "generic-vnf",
+                            "related-link": "/aai/v11/network/generic-vnfs/generic-vnf/fbb52a16-2c57-4212-802f-32dbba2204f2",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "generic-vnf.vnf-id",
+                                    "relationship-value": "fbb52a16-2c57-4212-802f-32dbba2204f2"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "generic-vnf.vnf-name",
+                                    "property-value": "fdfdfdf"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        ]
+    },
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/tenant-1",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "tenant-1"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AIN Web Tool-15-D-sspstMAIL"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/23cbbd1872864ea08aa53ade25d34172",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "23cbbd1872864ea08aa53ade25d34172"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AIN Web Tool-15-D-rtertet"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/ded2432abb5a4100801331d07787afc2",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "ded2432abb5a4100801331d07787afc2"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AIN/SMS-16-D-SSPecompFlvr2"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/ad5aab08f5f7435e9983311af543f311",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "ad5aab08f5f7435e9983311af543f311"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AINWebTool-15-X-PODECOMP"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/8071dc66981c4294b05483a1cddac801",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "8071dc66981c4294b05483a1cddac801"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "CESAR-100-X-ecompPODprivate"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/036f769581904ca08ead1415c22b9ec0",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "036f769581904ca08ead1415c22b9ec0"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AINWebTool-15-X-PODECOMPCLONE"
+                    }
+                ]
+            },
+            {
+                "related-to": "tenant",
+                "related-link": "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/att-aic/mtn6/tenants/tenant/c2475a36c5e04f12a21593849ae83420",
+                "relationship-data": [
+                    {
+                        "relationship-key": "cloud-region.cloud-owner",
+                        "relationship-value": "att-aic"
+                    },
+                    {
+                        "relationship-key": "cloud-region.cloud-region-id",
+                        "relationship-value": "mtn6"
+                    },
+                    {
+                        "relationship-key": "tenant.tenant-id",
+                        "relationship-value": "c2475a36c5e04f12a21593849ae83420"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "tenant.tenant-name",
+                        "property-value": "AIN/SMS-16-X-hope"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/sync/aai/service-subscription-service-subscription-3.json b/src/test/resources/sync/aai/service-subscription-service-subscription-3.json
new file mode 100644 (file)
index 0000000..39b46ad
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "service-type": "service-subscription-3",
+    "resource-version": "1495736709052",
+    "service-instances": {
+        "service-instance": [
+            {
+                "service-instance-id": "service-subscription-3",
+                "resource-version": "1495736709053"
+            }
+        ]
+    }
+}
\ No newline at end of file