From 7b42006c51d4f014f72ae39170544a85d2f09fb5 Mon Sep 17 00:00:00 2001
From: Shawn Severin
Date: Mon, 11 Dec 2017 15:42:52 -0500
Subject: Adding UI extensibility
Adding the ability for Sparky developers to create their own custom
front-end views
Issue-ID: AAI-542
Change-Id: I83f9608639799e3bf85b654f44a0a7a5a85ad264
Signed-off-by: Shawn Severin
---
pom.xml | 9 +-
.../v1/conf/HelloWorldBeans.xml | 8 -
.../inventory-ui-service/v1/conf/jaxrsBeans.groovy | 2 +-
.../v1/routes/helloServlet.route | 4 -
.../v1/routes/helloWorld.route | 4 -
.../v1/routes/jaxrsExample.route | 4 -
.../v1/routes/serverStaticContent.route | 4 -
.../routes/sparky-core-unifiedFilterRequest.route | 4 -
src/main/config/aaiEntityNodeDescriptors.json | 30 +
src/main/config/ajsc-override-web.xml | 34 +-
src/main/config/cadi.properties | 36 +
src/main/config/csp-cookie-filter.properties | 18 +
src/main/config/es_sv_mappings.json | 36 +
src/main/config/es_sv_settings.json | 36 +
src/main/config/runner-web.xml | 45 +-
src/main/docker/Dockerfile | 6 +-
.../java/org/onap/aai/sparky/JaxrsEchoService.java | 6 +-
.../java/org/onap/aai/sparky/JaxrsUserService.java | 61 +
src/main/java/org/onap/aai/sparky/Test.java | 27 +
.../search/AggregateSummaryProcessor.java | 238 +++
.../search/AggregateVnfSearchProvider.java | 160 ++
.../aggregatevnf/search/VnfSearchQueryBuilder.java | 184 +++
.../sync/AggregationSyncControllerFactory.java | 232 +++
.../aggregation/sync/AggregationSynchronizer.java | 778 ++++++++++
.../sync/HistoricalEntitySummarizer.java | 391 +++++
.../sync/HistoricalEntitySyncController.java | 90 ++
.../aai/sparky/analytics/AbstractStatistics.java | 42 +-
.../aai/sparky/analytics/HistoricalCounter.java | 82 +-
.../sync/AutoSuggestionSyncController.java | 97 ++
.../sync/AutosuggestionSynchronizer.java | 749 +++++++++
.../sync/VnfAliasSuggestionSynchronizer.java | 192 +++
.../sync/VnfAliasSyncController.java | 95 ++
.../common/search/CommonSearchSuggestion.java | 88 ++
.../org/onap/aai/sparky/config/Configurable.java | 43 -
.../config/exception/ConfigurationException.java | 31 -
.../sparky/config/oxm/CrossEntityReference.java | 1 -
.../config/oxm/CrossEntityReferenceDescriptor.java | 65 +
.../config/oxm/CrossEntityReferenceLookup.java | 154 ++
.../aai/sparky/config/oxm/GeoEntityDescriptor.java | 59 +
.../aai/sparky/config/oxm/GeoEntityLookup.java | 155 ++
.../sparky/config/oxm/GeoOxmEntityDescriptor.java | 69 +
.../aai/sparky/config/oxm/OxmEntityDescriptor.java | 142 +-
.../aai/sparky/config/oxm/OxmEntityLookup.java | 151 ++
.../onap/aai/sparky/config/oxm/OxmModelLoader.java | 500 ++----
.../sparky/config/oxm/OxmModelLoaderFilter.java | 90 --
.../aai/sparky/config/oxm/OxmModelProcessor.java | 31 +
.../sparky/config/oxm/SearchableEntityLookup.java | 138 ++
.../config/oxm/SearchableOxmEntityDescriptor.java | 73 +
.../config/oxm/SuggestionEntityDescriptor.java | 52 +
.../sparky/config/oxm/SuggestionEntityLookup.java | 197 +++
.../sync/CrossEntityReferenceSynchronizer.java | 949 ++++++++++++
.../aai/sparky/dal/ActiveInventoryAdapter.java | 460 ++++++
.../onap/aai/sparky/dal/ElasticSearchAdapter.java | 120 ++
.../onap/aai/sparky/dal/NetworkTransaction.java | 25 +-
.../aai/sparky/dal/aai/ActiveInventoryAdapter.java | 407 -----
.../dal/aai/ActiveInventoryDataProvider.java | 7 +-
.../dal/aai/ActiveInventoryEntityStatistics.java | 65 +-
...tiveInventoryProcessingExceptionStatistics.java | 7 +-
.../dal/aai/config/ActiveInventoryConfig.java | 74 +-
.../dal/aai/config/ActiveInventoryRestConfig.java | 134 +-
.../dal/aai/config/ActiveInventorySslConfig.java | 16 +-
.../org/onap/aai/sparky/dal/cache/EntityCache.java | 60 -
.../aai/sparky/dal/cache/InMemoryEntityCache.java | 107 --
.../sparky/dal/cache/PersistentEntityCache.java | 256 ---
.../dal/elasticsearch/ElasticSearchAdapter.java | 213 ---
.../elasticsearch/ElasticSearchDataProvider.java | 6 +-
.../ElasticSearchEntityStatistics.java | 46 +-
.../dal/elasticsearch/HashQueryResponse.java | 3 +-
.../sparky/dal/elasticsearch/SearchAdapter.java | 68 +-
.../elasticsearch/config/ElasticSearchConfig.java | 366 +----
.../sparky/dal/proxy/config/DataRouterConfig.java | 132 ++
.../dal/proxy/processor/AaiUiProxyProcessor.java | 227 +++
.../aai/sparky/dal/rest/RestClientBuilder.java | 10 +-
.../aai/sparky/dal/rest/RestfulDataAccessor.java | 107 +-
.../sparky/dal/sas/config/SearchServiceConfig.java | 5 +
.../ResettableStreamHttpServletRequest.java | 128 --
.../sparky/dataintegrity/config/DiUiConstants.java | 77 +
.../editattributes/AttributeEditProcessor.java | 182 +++
.../sparky/editattributes/AttributeUpdater.java | 366 +++++
.../editattributes/UserAuthorizationReader.java | 77 +
.../aai/sparky/editattributes/UserValidator.java | 65 +
.../sparky/editattributes/entity/EditRequest.java | 67 +
.../exception/AttributeUpdateException.java | 60 +
.../inventory/EntityHistoryQueryBuilder.java | 143 ++
.../inventory/GeoVisualizationProcessor.java | 202 +++
.../sparky/inventory/entity/GeoIndexDocument.java | 292 ++++
.../inventory/entity/TopographicalEntity.java | 220 +++
.../org/onap/aai/sparky/logging/AaiUiMsgs.java | 53 +-
.../onap/aai/sparky/logging/util/ServletUtils.java | 161 ++
.../sparky/search/EntityCountHistoryProcessor.java | 417 +++++
.../org/onap/aai/sparky/search/SearchResponse.java | 99 ++
.../org/onap/aai/sparky/search/Suggestion.java | 57 -
.../org/onap/aai/sparky/search/SuggestionList.java | 70 -
.../aai/sparky/search/UnifiedSearchProcessor.java | 212 +++
.../aai/sparky/search/VnfSearchQueryBuilder.java | 174 ---
.../onap/aai/sparky/search/VnfSearchService.java | 348 -----
.../onap/aai/sparky/search/api/SearchProvider.java | 34 +
.../aai/sparky/search/config/SuggestionConfig.java | 6 +-
.../search/entity/ExternalSearchRequestEntity.java | 69 +
.../sparky/search/entity/QuerySearchEntity.java | 71 +
.../aai/sparky/search/entity/SearchSuggestion.java | 37 +
.../search/filters/FilterElasticSearchAdapter.java | 7 +-
.../aai/sparky/search/filters/FilterProcessor.java | 1 -
.../search/filters/config/FiltersConfig.java | 2 +-
.../search/registry/SearchProviderRegistry.java | 74 +
.../org/onap/aai/sparky/security/EcompSso.java | 21 +-
.../sparky/security/filter/CspCookieFilter.java | 274 ++++
.../aai/sparky/security/filter/LoginFilter.java | 19 +-
.../security/portal/PortalRestAPIServiceImpl.java | 33 +-
.../portal/config/PortalAuthenticationConfig.java | 1 +
.../sparky/suggestivesearch/SuggestionEntity.java | 61 -
.../sparky/sync/AbstractEntitySynchronizer.java | 564 +++++++
.../aai/sparky/sync/ElasticSearchIndexCleaner.java | 607 ++++++++
.../sparky/sync/ElasticSearchSchemaFactory.java | 109 ++
.../org/onap/aai/sparky/sync/IndexCleaner.java | 55 +
.../aai/sparky/sync/IndexIntegrityValidator.java | 176 +++
.../onap/aai/sparky/sync/IndexSynchronizer.java | 65 +
.../org/onap/aai/sparky/sync/IndexValidator.java | 56 +
.../org/onap/aai/sparky/sync/SyncController.java | 96 ++
.../onap/aai/sparky/sync/SyncControllerImpl.java | 692 +++++++++
.../aai/sparky/sync/SyncControllerRegistrar.java | 27 +
.../aai/sparky/sync/SyncControllerRegistry.java | 48 +
.../aai/sparky/sync/SyncControllerService.java | 220 +++
.../aai/sparky/sync/SynchronizerConstants.java | 63 +
.../onap/aai/sparky/sync/TaskProcessingStats.java | 133 ++
.../aai/sparky/sync/TransactionRateMonitor.java | 73 +
.../sync/config/ElasticSearchEndpointConfig.java | 70 +
.../sync/config/ElasticSearchSchemaConfig.java | 75 +
.../sync/config/NetworkStatisticsConfig.java | 237 +++
.../sparky/sync/config/SyncControllerConfig.java | 303 ++++
.../aai/sparky/sync/entity/AggregationEntity.java | 102 ++
.../sync/entity/AggregationSuggestionEntity.java | 104 ++
.../onap/aai/sparky/sync/entity/IndexDocument.java | 39 +
.../sync/entity/IndexableCrossEntityReference.java | 99 ++
.../aai/sparky/sync/entity/IndexableEntity.java | 98 ++
.../aai/sparky/sync/entity/MergableEntity.java | 57 +
.../aai/sparky/sync/entity/ObjectIdCollection.java | 76 +
.../aai/sparky/sync/entity/SearchableEntity.java | 144 ++
.../aai/sparky/sync/entity/SelfLinkDescriptor.java | 90 ++
.../sparky/sync/entity/SuggestionSearchEntity.java | 326 ++++
.../sparky/sync/entity/TransactionStorageType.java | 54 +
.../sparky/sync/enumeration/OperationState.java | 30 +
.../sparky/sync/enumeration/SynchronizerState.java | 30 +
.../sync/task/PerformActiveInventoryRetrieval.java | 100 ++
.../sparky/sync/task/PerformElasticSearchPut.java | 88 ++
.../sync/task/PerformElasticSearchRetrieval.java | 72 +
.../sync/task/PerformElasticSearchUpdate.java | 80 +
.../aai/sparky/sync/task/StoreDocumentTask.java | 90 ++
.../aai/sparky/sync/task/SyncControllerTask.java | 53 +
.../synchronizer/AbstractEntitySynchronizer.java | 568 -------
.../AggregationSuggestionSynchronizer.java | 183 ---
.../synchronizer/AggregationSynchronizer.java | 771 ---------
.../synchronizer/AutosuggestionSynchronizer.java | 737 ---------
.../CrossEntityReferenceSynchronizer.java | 907 -----------
.../synchronizer/ElasticSearchIndexCleaner.java | 795 ----------
.../onap/aai/sparky/synchronizer/IndexCleaner.java | 55 -
.../synchronizer/IndexIntegrityValidator.java | 227 ---
.../aai/sparky/synchronizer/IndexSynchronizer.java | 65 -
.../aai/sparky/synchronizer/IndexValidator.java | 56 -
.../aai/sparky/synchronizer/MyErrorHandler.java | 111 --
.../synchronizer/SearchableEntitySynchronizer.java | 767 ---------
.../aai/sparky/synchronizer/SyncController.java | 476 ------
.../onap/aai/sparky/synchronizer/SyncHelper.java | 568 -------
.../sparky/synchronizer/TaskProcessingStats.java | 189 ---
.../synchronizer/TransactionRateController.java | 110 --
.../config/NetworkStatisticsConfig.java | 237 ---
.../config/SynchronizerConfiguration.java | 544 -------
.../synchronizer/config/SynchronizerConstants.java | 60 -
.../synchronizer/config/TaskProcessorConfig.java | 325 ----
.../synchronizer/entity/AggregationEntity.java | 146 --
.../entity/AggregationSuggestionEntity.java | 119 --
.../sparky/synchronizer/entity/IndexDocument.java | 42 -
.../entity/IndexableCrossEntityReference.java | 163 --
.../synchronizer/entity/IndexableEntity.java | 139 --
.../sparky/synchronizer/entity/MergableEntity.java | 68 -
.../synchronizer/entity/ObjectIdCollection.java | 90 --
.../synchronizer/entity/SearchableEntity.java | 196 ---
.../synchronizer/entity/SelfLinkDescriptor.java | 90 --
.../entity/SuggestionSearchEntity.java | 349 -----
.../entity/TransactionStorageType.java | 69 -
.../synchronizer/enumeration/OperationState.java | 30 -
.../enumeration/SynchronizerState.java | 30 -
.../filter/ElasticSearchSynchronizerFilter.java | 136 --
.../task/CollectEntitySelfLinkTask.java | 104 --
.../task/CollectEntityTypeSelfLinksTask.java | 105 --
.../task/GetCrossEntityReferenceEntityTask.java | 105 --
.../task/PerformActiveInventoryRetrieval.java | 151 --
.../synchronizer/task/PerformElasticSearchPut.java | 140 --
.../task/PerformElasticSearchRetrieval.java | 110 --
.../task/PerformElasticSearchUpdate.java | 152 --
.../task/PersistOperationResultToDisk.java | 157 --
.../task/RetrieveOperationResultFromDisk.java | 133 --
.../synchronizer/task/StoreDocumentTask.java | 137 --
.../sparky/topology/sync/GeoSyncController.java | 95 ++
.../aai/sparky/topology/sync/GeoSynchronizer.java | 497 ++++++
.../org/onap/aai/sparky/util/ConfigHelper.java | 2 +-
.../java/org/onap/aai/sparky/util/Encryptor.java | 78 +-
.../java/org/onap/aai/sparky/util/ErrorUtil.java | 1 -
.../org/onap/aai/sparky/util/KeystoreBuilder.java | 24 +-
.../java/org/onap/aai/sparky/util/NodeUtils.java | 144 +-
.../org/onap/aai/sparky/util/RestletUtils.java | 118 ++
.../org/onap/aai/sparky/util/ServletUtils.java | 161 --
.../aai/sparky/util/SuggestionsPermutation.java | 85 +-
.../java/org/onap/aai/sparky/util/TreeWalker.java | 10 +-
.../org/onap/aai/sparky/util/test/Encryptor.java | 83 -
.../onap/aai/sparky/util/test/KeystoreBuilder.java | 541 -------
.../viewandinspect/EntityTypeAggregation.java | 13 +-
.../SchemaVisualizationProcessor.java | 174 +++
.../config/TierSupportUiConstants.java | 352 +----
.../viewandinspect/config/VisualizationConfig.java | 219 ---
.../config/VisualizationConfigs.java | 169 ++
.../viewandinspect/entity/ActiveInventoryNode.java | 64 +-
.../entity/D3VisualizationOutput.java | 66 -
.../sparky/viewandinspect/entity/GraphRequest.java | 56 +
.../aai/sparky/viewandinspect/entity/JsonNode.java | 70 +-
.../aai/sparky/viewandinspect/entity/NodeMeta.java | 22 +-
.../entity/NodeProcessingTransaction.java | 2 +-
.../viewandinspect/entity/QuerySearchEntity.java | 72 -
.../sparky/viewandinspect/entity/Relationship.java | 4 +-
.../viewandinspect/entity/RelationshipList.java | 18 +-
.../viewandinspect/entity/SearchResponse.java | 90 --
.../entity/SearchableEntityList.java | 115 ++
.../entity/SelfLinkDeterminationTransaction.java | 3 +-
.../sparky/viewandinspect/entity/Violations.java | 125 --
.../enumeration/NodeProcessingAction.java | 1 +
.../search/ViewInspectSearchProvider.java | 440 ++++++
.../services/SearchServiceWrapper.java | 980 ------------
.../services/VisualizationContext.java | 97 +-
.../services/VisualizationService.java | 110 +-
.../services/VisualizationTransformer.java | 122 +-
.../viewandinspect/servlet/SearchServlet.java | 224 ---
.../servlet/VisualizationServlet.java | 200 ---
.../task/CollectNodeSelfLinkTask.java | 29 -
.../task/PerformNodeSelfLinkProcessingTask.java | 31 +-
.../task/PerformSelfLinkDeterminationTask.java | 16 +-
.../sync/ViewInspectEntitySynchronizer.java | 783 ++++++++++
.../sync/ViewInspectSyncController.java | 129 ++
src/main/resources/extApps/aai.war | Bin 0 -> 1372092 bytes
src/main/resources/extApps/aai.xml | 1 -
src/main/resources/logging/AAIUIMsgs.properties | 125 +-
src/main/scripts/encNameValue.sh | 20 +
src/main/scripts/start.sh | 61 +-
.../onap/aai/sparky/FilterByContainsClassName.java | 22 -
.../java/org/onap/aai/sparky/SparkyPojoTest.java | 221 ---
.../sparky/analytics/AbstractStatisticsTest.java | 46 -
.../sparky/analytics/AveragingRingBufferTest.java | 64 +-
.../aai/sparky/analytics/HistogramSamplerTest.java | 50 +-
.../sparky/analytics/HistoricalCounterTest.java | 87 +-
.../analytics/TransactionRateControllerTest.java | 48 +-
.../config/oxm/CrossEntityReferenceTest.java | 27 -
.../config/oxm/OxmModelLoaderFilterTest.java | 57 -
.../aai/sparky/config/oxm/OxmModelLoaderTest.java | 50 -
.../aai/sparky/dal/NetworkTransactionTest.java | 36 -
.../sparky/dal/aai/ActiveInventoryAdapterTest.java | 104 --
.../aai/ActiveInventoryEntityStatisticsTest.java | 75 -
...InventoryProcessingExceptionStatisticsTest.java | 62 -
.../dal/aai/config/ActiveInventoryConfigTest.java | 381 ++---
.../dal/aai/config/ActiveInventoryConfigUtil.java | 87 ++
.../aai/config/ActiveInventoryRestConfigTest.java | 484 +++---
.../aai/config/ActiveInventorySslConfigTest.java | 58 +-
.../sparky/dal/cache/InMemoryEntityCacheTest.java | 26 -
.../dal/elasticsearch/ElasticSearchConfigTest.java | 182 +--
.../ElasticSearchEntityStatisticsTest.java | 101 --
.../entity/AutoSuggestDocumentEntity.java | 48 +-
.../entity/AutoSuggestDocumentEntityFields.java | 48 +-
.../entity/AutoSuggestElasticHitEntity.java | 48 +-
.../entity/AutoSuggestElasticHitsEntity.java | 48 +-
.../entity/AutoSuggestElasticSearchResponse.java | 48 +-
.../dal/elasticsearch/entity/BucketEntity.java | 48 +-
.../dal/elasticsearch/entity/ElasticHit.java | 48 +-
.../elasticsearch/entity/ElasticHitsEntity.java | 48 +-
.../entity/ElasticSearchAggegrationResponse.java | 48 +-
.../entity/ElasticSearchAggregation.java | 48 +-
.../entity/ElasticSearchCountResponse.java | 48 +-
.../dal/elasticsearch/entity/PayloadEntity.java | 48 +-
.../proxy/processor/AaiUiProxyProcessorTest.java | 112 ++
.../dal/proxy/processor/DataRouterConfigUtil.java | 50 +
.../aai/sparky/dal/rest/RestClientBuilderTest.java | 63 +-
.../dal/rest/RestOperationalStatisticsTest.java | 210 ---
.../sparky/dal/rest/RestfulDataAccessorTest.java | 51 +-
.../aai/sparky/dal/sas/entity/DocumentEntity.java | 48 +-
.../sparky/dal/sas/entity/EntityCountResponse.java | 48 +-
.../dal/sas/entity/GroupByAggregationEntity.java | 48 +-
.../entity/GroupByAggregationResponseEntity.java | 48 +-
.../onap/aai/sparky/dal/sas/entity/HitEntity.java | 48 +-
.../sas/entity/SearchAbstractionEntityBuilder.java | 71 +-
.../dal/sas/entity/SearchAbstractionResponse.java | 48 +-
.../aai/sparky/dal/sas/entity/SearchResult.java | 48 +-
.../dataintegrity/config/DiUiConstantsTest.java | 65 +
.../editattributes/AttributeUpdaterTest.java | 143 ++
.../sparky/editattributes/EditAttributesTest.java | 219 +++
.../TestUserAuthorizationReader.java | 113 ++
.../sparky/editattributes/TestUserValidator.java | 137 ++
.../inventory/EntityHistoryQueryBuilderTest.java | 33 +
.../aai/sparky/inventory/GeoIndexDocumentTest.java | 121 ++
.../aai/sparky/logging/util/LoggingUtilsTest.java | 26 +
.../search/EntityCountHistoryProcessorTest.java | 119 ++
.../sparky/search/UnifiedSearchProcessorTest.java | 644 ++++++++
.../sparky/search/VnfSearchQueryBuilderTest.java | 77 -
.../aai/sparky/search/VnfSearchServiceTest.java | 94 --
.../sparky/search/filters/FilterProcessorTest.java | 31 +-
.../security/SecurityContextFactoryImplTest.java | 48 +-
.../portal/TestPortalRestAPIServiceImpl.java | 66 +-
.../sparky/security/portal/TestUserManager.java | 117 +-
.../AggregationSuggestionSynchronizerTest.java | 91 --
.../synchronizer/AsyncRateControlTester.java | 55 +-
.../aai/sparky/synchronizer/IndexDocumentTest.java | 53 +-
.../sparky/synchronizer/SyncControllerBuilder.java | 892 +++++------
.../synchronizer/SyncControllerServiceTest.java | 34 +
.../sparky/synchronizer/SyncControllerTest.java | 86 -
.../aai/sparky/synchronizer/SyncHelperTest.java | 126 --
.../sparky/synchronizer/TestSyncController.java | 177 +++
.../config/SynchronizerConfigurationTest.java | 395 -----
.../entity/AggregationSuggestionEntityTest.java | 9 +-
.../entity/SuggestionSearchEntityTest.java | 161 ++
.../task/PerformActiveInventoryRetrievalTest.java | 87 ++
.../aai/sparky/util/CaptureLoggerAppender.java | 48 +-
.../aai/sparky/util/ElasticEntitySummarizer.java | 118 +-
.../aai/sparky/util/ElasticGarbageInjector.java | 170 --
.../onap/aai/sparky/util/EncryptConvertorTest.java | 14 -
.../org/onap/aai/sparky/util/ExceptionHelper.java | 48 +-
.../onap/aai/sparky/util/HttpServletHelper.java | 48 +-
.../onap/aai/sparky/util/KeystoreBuilderTest.java | 105 --
.../org/onap/aai/sparky/util/LogValidator.java | 55 +-
.../org/onap/aai/sparky/util/NodeUtilsTest.java | 517 ------
.../onap/aai/sparky/util/OxmModelLoaderTest.java | 166 --
.../sparky/util/SuggestionsPermutationTest.java | 201 +++
.../sparky/util/SuggestionsPermutationsTest.java | 36 -
.../org/onap/aai/sparky/util/TreeWalkerTest.java | 50 +-
.../viewandinspect/ActiveInventoryNodeTester.java | 354 -----
.../sparky/viewandinspect/SearchAdapterTest.java | 53 +-
.../sparky/viewandinspect/SearchResponseTest.java | 54 +-
.../sparky/viewandinspect/SearchServletTest.java | 1639 ++++++++++----------
.../viewandinspect/SearchableGroupsTest.java | 48 +-
.../ViewAndInspectSearchRequestTest.java | 50 +-
.../config/VisualizationConfigTest.java | 81 +
.../entity/ActiveInventoryNodeTest.java | 101 ++
.../viewandinspect/entity/EntityEntryTest.java | 68 +-
.../viewandinspect/entity/GraphRequestTest.java | 56 +
.../viewandinspect/entity/InlineMessageTest.java | 55 +
.../viewandinspect/entity/JsonNodeLinkTest.java | 56 +
.../viewandinspect/entity/NodeDebugTest.java | 57 +
.../sparky/viewandinspect/entity/NodeMetaTest.java | 87 ++
.../viewandinspect/entity/QueryParamsTest.java | 56 +
.../viewandinspect/entity/QueryRequestTest.java | 54 +
.../entity/RelatedToPropertyTest.java | 54 +
.../entity/RelationshipDataTest.java | 54 +
.../viewandinspect/entity/SearchResponseTest.java | 52 +
.../SelfLinkDeterminationTransactionTest.java | 67 +
.../services/VisualizationContextTest.java | 141 --
.../services/VisualizationServiceTest.java | 96 --
.../PerformNodeSelfLinkProcessingTaskTest.java | 232 +++
src/test/resources/appconfig/aai.properties | 87 --
.../resources/appconfig/elasticsearch.properties | 70 -
.../appconfig/etc/aaiEntityNodeDescriptors.json | 188 ---
src/test/resources/appconfig/etc/ajsc-chef.jks | Bin 5256 -> 0 bytes
src/test/resources/appconfig/etc/ajsc-jetty.xml | 128 --
.../resources/appconfig/etc/ajsc-override-web.xml | 70 -
src/test/resources/appconfig/etc/ajscJetty.jks | Bin 3736 -> 0 bytes
.../appconfig/etc/autoSuggestMappings.json | 10 -
.../appconfig/etc/autoSuggestSettings.json | 21 -
.../resources/appconfig/etc/dynamicMappings.json | 14 -
.../appconfig/etc/entityCountHistoryMappings.json | 16 -
src/test/resources/appconfig/etc/es_mappings.json | 32 -
src/test/resources/appconfig/etc/es_settings.json | 36 -
.../appconfig/etc/jul-redirect.properties | 13 -
src/test/resources/appconfig/etc/keyfile | 27 -
src/test/resources/appconfig/etc/runner-web.xml | 112 --
src/test/resources/appconfig/roles.config | 6 -
.../resources/appconfig/search-service.properties | 29 -
.../appconfig/suggestive-search.properties | 27 -
.../resources/appconfig/synchronizer.properties | 33 -
.../portal/portal-authentication.properties | 2 +-
...estionEntity_getIndexDocumentJson_expected.json | 1 -
.../user-auth-reader/authorized-users-empty.config | 0
.../user-auth-reader/authorized-users.config | 3 +
.../user-validator/authorized-users.config | 3 +
377 files changed, 25272 insertions(+), 25501 deletions(-)
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/HelloWorldBeans.xml
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloServlet.route
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloWorld.route
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/jaxrsExample.route
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/serverStaticContent.route
delete mode 100644 src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/sparky-core-unifiedFilterRequest.route
create mode 100644 src/main/config/cadi.properties
create mode 100644 src/main/config/csp-cookie-filter.properties
create mode 100644 src/main/config/es_sv_mappings.json
create mode 100644 src/main/config/es_sv_settings.json
create mode 100644 src/main/java/org/onap/aai/sparky/JaxrsUserService.java
create mode 100644 src/main/java/org/onap/aai/sparky/Test.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateSummaryProcessor.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProvider.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregatevnf/search/VnfSearchQueryBuilder.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSyncControllerFactory.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySummarizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySyncController.java
create mode 100644 src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutoSuggestionSyncController.java
create mode 100644 src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSuggestionSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSyncController.java
create mode 100644 src/main/java/org/onap/aai/sparky/common/search/CommonSearchSuggestion.java
delete mode 100644 src/main/java/org/onap/aai/sparky/config/Configurable.java
delete mode 100644 src/main/java/org/onap/aai/sparky/config/exception/ConfigurationException.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceLookup.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityLookup.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/GeoOxmEntityDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityLookup.java
delete mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderFilter.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/OxmModelProcessor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/SearchableEntityLookup.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/SearchableOxmEntityDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityLookup.java
create mode 100644 src/main/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/dal/ActiveInventoryAdapter.java
create mode 100644 src/main/java/org/onap/aai/sparky/dal/ElasticSearchAdapter.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryAdapter.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/cache/EntityCache.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/cache/InMemoryEntityCache.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/cache/PersistentEntityCache.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/elasticsearch/ElasticSearchAdapter.java
create mode 100644 src/main/java/org/onap/aai/sparky/dal/proxy/config/DataRouterConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/dal/proxy/processor/AaiUiProxyProcessor.java
delete mode 100644 src/main/java/org/onap/aai/sparky/dal/servlet/ResettableStreamHttpServletRequest.java
create mode 100644 src/main/java/org/onap/aai/sparky/dataintegrity/config/DiUiConstants.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/AttributeEditProcessor.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/AttributeUpdater.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/UserAuthorizationReader.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/UserValidator.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/entity/EditRequest.java
create mode 100644 src/main/java/org/onap/aai/sparky/editattributes/exception/AttributeUpdateException.java
create mode 100644 src/main/java/org/onap/aai/sparky/inventory/EntityHistoryQueryBuilder.java
create mode 100644 src/main/java/org/onap/aai/sparky/inventory/GeoVisualizationProcessor.java
create mode 100644 src/main/java/org/onap/aai/sparky/inventory/entity/GeoIndexDocument.java
create mode 100644 src/main/java/org/onap/aai/sparky/inventory/entity/TopographicalEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/logging/util/ServletUtils.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/SearchResponse.java
delete mode 100644 src/main/java/org/onap/aai/sparky/search/Suggestion.java
delete mode 100644 src/main/java/org/onap/aai/sparky/search/SuggestionList.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/UnifiedSearchProcessor.java
delete mode 100644 src/main/java/org/onap/aai/sparky/search/VnfSearchQueryBuilder.java
delete mode 100644 src/main/java/org/onap/aai/sparky/search/VnfSearchService.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/api/SearchProvider.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/entity/ExternalSearchRequestEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/entity/QuerySearchEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/entity/SearchSuggestion.java
create mode 100644 src/main/java/org/onap/aai/sparky/search/registry/SearchProviderRegistry.java
create mode 100644 src/main/java/org/onap/aai/sparky/security/filter/CspCookieFilter.java
delete mode 100644 src/main/java/org/onap/aai/sparky/suggestivesearch/SuggestionEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/AbstractEntitySynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/ElasticSearchIndexCleaner.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/ElasticSearchSchemaFactory.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/IndexCleaner.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/IndexIntegrityValidator.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/IndexSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/IndexValidator.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SyncController.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SyncControllerImpl.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SyncControllerRegistrar.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SyncControllerRegistry.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SyncControllerService.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/SynchronizerConstants.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/TaskProcessingStats.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/TransactionRateMonitor.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/config/ElasticSearchEndpointConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/config/ElasticSearchSchemaConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/config/NetworkStatisticsConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/config/SyncControllerConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/AggregationEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/AggregationSuggestionEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/IndexDocument.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/IndexableCrossEntityReference.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/IndexableEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/MergableEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/ObjectIdCollection.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/SearchableEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/SelfLinkDescriptor.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/SuggestionSearchEntity.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/entity/TransactionStorageType.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/enumeration/OperationState.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/enumeration/SynchronizerState.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/PerformActiveInventoryRetrieval.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/PerformElasticSearchPut.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/PerformElasticSearchRetrieval.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/PerformElasticSearchUpdate.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/StoreDocumentTask.java
create mode 100644 src/main/java/org/onap/aai/sparky/sync/task/SyncControllerTask.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/AbstractEntitySynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/AggregationSuggestionSynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/AggregationSynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/AutosuggestionSynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/CrossEntityReferenceSynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/ElasticSearchIndexCleaner.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/IndexCleaner.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/IndexIntegrityValidator.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/IndexSynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/IndexValidator.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/MyErrorHandler.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/SearchableEntitySynchronizer.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/SyncController.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/SyncHelper.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/TaskProcessingStats.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/TransactionRateController.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/config/NetworkStatisticsConfig.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/config/SynchronizerConfiguration.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/config/SynchronizerConstants.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/config/TaskProcessorConfig.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/AggregationEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/AggregationSuggestionEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/IndexDocument.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/IndexableCrossEntityReference.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/IndexableEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/MergableEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/ObjectIdCollection.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/SearchableEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/SelfLinkDescriptor.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/SuggestionSearchEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/entity/TransactionStorageType.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/enumeration/OperationState.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/enumeration/SynchronizerState.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/filter/ElasticSearchSynchronizerFilter.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/CollectEntitySelfLinkTask.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/CollectEntityTypeSelfLinksTask.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/GetCrossEntityReferenceEntityTask.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/PerformActiveInventoryRetrieval.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/PerformElasticSearchPut.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/PerformElasticSearchRetrieval.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/PerformElasticSearchUpdate.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/PersistOperationResultToDisk.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/RetrieveOperationResultFromDisk.java
delete mode 100644 src/main/java/org/onap/aai/sparky/synchronizer/task/StoreDocumentTask.java
create mode 100644 src/main/java/org/onap/aai/sparky/topology/sync/GeoSyncController.java
create mode 100644 src/main/java/org/onap/aai/sparky/topology/sync/GeoSynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/util/RestletUtils.java
delete mode 100644 src/main/java/org/onap/aai/sparky/util/ServletUtils.java
delete mode 100644 src/main/java/org/onap/aai/sparky/util/test/Encryptor.java
delete mode 100644 src/main/java/org/onap/aai/sparky/util/test/KeystoreBuilder.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/SchemaVisualizationProcessor.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/config/VisualizationConfig.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/config/VisualizationConfigs.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/entity/GraphRequest.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/entity/QuerySearchEntity.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/entity/SearchResponse.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/entity/SearchableEntityList.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/entity/Violations.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/search/ViewInspectSearchProvider.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/services/SearchServiceWrapper.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/servlet/SearchServlet.java
delete mode 100644 src/main/java/org/onap/aai/sparky/viewandinspect/servlet/VisualizationServlet.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewinspect/sync/ViewInspectEntitySynchronizer.java
create mode 100644 src/main/java/org/onap/aai/sparky/viewinspect/sync/ViewInspectSyncController.java
create mode 100644 src/main/resources/extApps/aai.war
create mode 100644 src/main/scripts/encNameValue.sh
delete mode 100644 src/test/java/org/onap/aai/sparky/FilterByContainsClassName.java
delete mode 100644 src/test/java/org/onap/aai/sparky/SparkyPojoTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/analytics/AbstractStatisticsTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderFilterTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/NetworkTransactionTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/aai/ActiveInventoryAdapterTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/aai/ActiveInventoryEntityStatisticsTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/aai/ActiveInventoryProcessingExceptionStatisticsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/dal/aai/config/ActiveInventoryConfigUtil.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/cache/InMemoryEntityCacheTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/elasticsearch/ElasticSearchEntityStatisticsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/dal/proxy/processor/AaiUiProxyProcessorTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/dal/proxy/processor/DataRouterConfigUtil.java
delete mode 100644 src/test/java/org/onap/aai/sparky/dal/rest/RestOperationalStatisticsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/dataintegrity/config/DiUiConstantsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/editattributes/AttributeUpdaterTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/editattributes/EditAttributesTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/editattributes/TestUserAuthorizationReader.java
create mode 100644 src/test/java/org/onap/aai/sparky/editattributes/TestUserValidator.java
create mode 100644 src/test/java/org/onap/aai/sparky/inventory/EntityHistoryQueryBuilderTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/inventory/GeoIndexDocumentTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/logging/util/LoggingUtilsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/search/EntityCountHistoryProcessorTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/search/UnifiedSearchProcessorTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/search/VnfSearchQueryBuilderTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/search/VnfSearchServiceTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/AggregationSuggestionSynchronizerTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/SyncControllerServiceTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/SyncControllerTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/SyncHelperTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/TestSyncController.java
delete mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/config/SynchronizerConfigurationTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/entity/SuggestionSearchEntityTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/synchronizer/task/PerformActiveInventoryRetrievalTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/ElasticGarbageInjector.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/EncryptConvertorTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/KeystoreBuilderTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/NodeUtilsTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/OxmModelLoaderTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/util/SuggestionsPermutationTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/util/SuggestionsPermutationsTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/ActiveInventoryNodeTester.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/config/VisualizationConfigTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/ActiveInventoryNodeTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/GraphRequestTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/InlineMessageTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/JsonNodeLinkTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/NodeDebugTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/NodeMetaTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/QueryParamsTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/QueryRequestTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/RelatedToPropertyTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/RelationshipDataTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/SearchResponseTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/entity/SelfLinkDeterminationTransactionTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/services/VisualizationContextTest.java
delete mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/services/VisualizationServiceTest.java
create mode 100644 src/test/java/org/onap/aai/sparky/viewandinspect/task/PerformNodeSelfLinkProcessingTaskTest.java
delete mode 100644 src/test/resources/appconfig/aai.properties
delete mode 100644 src/test/resources/appconfig/elasticsearch.properties
delete mode 100644 src/test/resources/appconfig/etc/aaiEntityNodeDescriptors.json
delete mode 100644 src/test/resources/appconfig/etc/ajsc-chef.jks
delete mode 100644 src/test/resources/appconfig/etc/ajsc-jetty.xml
delete mode 100644 src/test/resources/appconfig/etc/ajsc-override-web.xml
delete mode 100644 src/test/resources/appconfig/etc/ajscJetty.jks
delete mode 100644 src/test/resources/appconfig/etc/autoSuggestMappings.json
delete mode 100644 src/test/resources/appconfig/etc/autoSuggestSettings.json
delete mode 100644 src/test/resources/appconfig/etc/dynamicMappings.json
delete mode 100644 src/test/resources/appconfig/etc/entityCountHistoryMappings.json
delete mode 100644 src/test/resources/appconfig/etc/es_mappings.json
delete mode 100644 src/test/resources/appconfig/etc/es_settings.json
delete mode 100644 src/test/resources/appconfig/etc/jul-redirect.properties
delete mode 100644 src/test/resources/appconfig/etc/keyfile
delete mode 100644 src/test/resources/appconfig/etc/runner-web.xml
delete mode 100644 src/test/resources/appconfig/roles.config
delete mode 100644 src/test/resources/appconfig/search-service.properties
delete mode 100644 src/test/resources/appconfig/suggestive-search.properties
delete mode 100644 src/test/resources/appconfig/synchronizer.properties
delete mode 100644 src/test/resources/sync/entity/AggregationSuggestionEntity_getIndexDocumentJson_expected.json
create mode 100644 src/test/resources/user-auth-reader/authorized-users-empty.config
create mode 100644 src/test/resources/user-auth-reader/authorized-users.config
create mode 100644 src/test/resources/user-validator/authorized-users.config
diff --git a/pom.xml b/pom.xml
index 5f4921e..a5ddf4f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
v1
2.0.0
/appl/${project.artifactId}
- org.amdocs.aaiee
+ org.onap.aai
sparky-fe
1.1.0-SNAPSHOT
@@ -56,7 +56,6 @@
-
org.mockito
mockito-all
@@ -405,9 +404,9 @@
- org.onap.aai.sparky-fe
- sparky-fe
- 1.1.0-SNAPSHOT
+ ${frontEndGroupdId}
+ ${frontEndArtifactId}
+ ${frontEndVersion}
war
${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extApps/
aai.war
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/HelloWorldBeans.xml b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/HelloWorldBeans.xml
deleted file mode 100644
index c052560..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/HelloWorldBeans.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/jaxrsBeans.groovy b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/jaxrsBeans.groovy
index b65cb80..da9b558 100644
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/jaxrsBeans.groovy
+++ b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/conf/jaxrsBeans.groovy
@@ -3,7 +3,7 @@ beans{
xmlns jaxrs: "http://cxf.apache.org/jaxrs"
xmlns util: "http://www.springframework.org/schema/util"
- echoService(org.onap.aai.sparky.JaxrsEchoService)
+ echoService(org.openecomp.sparky.JaxrsEchoService)
util.list(id: 'jaxrsServices') {
ref(bean:'echoService')
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloServlet.route b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloServlet.route
deleted file mode 100644
index 5ede9c1..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloServlet.route
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloWorld.route b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloWorld.route
deleted file mode 100644
index bc3e178..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/helloWorld.route
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/jaxrsExample.route b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/jaxrsExample.route
deleted file mode 100644
index 25c1977..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/jaxrsExample.route
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/serverStaticContent.route b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/serverStaticContent.route
deleted file mode 100644
index bf221c6..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/serverStaticContent.route
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/sparky-core-unifiedFilterRequest.route b/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/sparky-core-unifiedFilterRequest.route
deleted file mode 100644
index 36cf518..0000000
--- a/src/main/ajsc/inventory-ui-service_v1/inventory-ui-service/v1/routes/sparky-core-unifiedFilterRequest.route
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/config/aaiEntityNodeDescriptors.json b/src/main/config/aaiEntityNodeDescriptors.json
index bf95f28..e72bab0 100644
--- a/src/main/config/aaiEntityNodeDescriptors.json
+++ b/src/main/config/aaiEntityNodeDescriptors.json
@@ -129,6 +129,21 @@
"className": "node-button",
"r": "10"
}
+ },
+ {
+ "type": "button",
+ "name": "icon_triangle_warning",
+ "class": "node-button",
+ "shapeAttributes": {
+ "offset": {
+ "x": "46",
+ "y": "-12"
+ }
+ },
+ "svgAttributes": {
+ "className": "node-button",
+ "r": "10"
+ }
}]
},
"selectedNodeClass": {
@@ -183,6 +198,21 @@
"className": "node-button",
"r": "10"
}
+ },
+ {
+ "type": "button",
+ "name": "icon_triangle_warning",
+ "class": "node-button",
+ "shapeAttributes": {
+ "offset": {
+ "x": "46",
+ "y": "-12"
+ }
+ },
+ "svgAttributes": {
+ "className": "node-button",
+ "r": "10"
+ }
}]
}
}
\ No newline at end of file
diff --git a/src/main/config/ajsc-override-web.xml b/src/main/config/ajsc-override-web.xml
index c66ac89..e267829 100644
--- a/src/main/config/ajsc-override-web.xml
+++ b/src/main/config/ajsc-override-web.xml
@@ -3,34 +3,22 @@
-
-
-
-
- ElasticSearchSynchronizerFilter
- /nothingShouldBeSentHere/*
-
-
-
- OxmModelLoaderFilter
- /nothingShouldBeSentHereEither/*
+
+
+ LoginFilter
+ /*
PortalRestAPIProxy
/api/v2/*
-
-
-
- VisualizationServlet
- /visualization/*
-
-
+
+
springSecurityFilterChain
/*
-
-
+
+
ManagementServlet
/mgmt
@@ -46,12 +34,6 @@
/services/*
-
- SearchServlet
- /elasticSearchQuery/*
- /search/*
-
-
jsp
*.jsp
diff --git a/src/main/config/cadi.properties b/src/main/config/cadi.properties
new file mode 100644
index 0000000..83a5ce0
--- /dev/null
+++ b/src/main/config/cadi.properties
@@ -0,0 +1,36 @@
+#This properties file is used for defining AAF properties related to the CADI framework. This file is used for running AAF framework
+
+#In order to test functionality of cadi-ajsc-plugin locally cross domain cookie. Cadi "should" find your hostname for you.
+#However, we have seen some situations where this fails. A Local testing
+#modification can include modifying your hosts file so that you can use "mywebserver.att.com" for your localhost in order
+#to test/verify GLO functionality locally. If you are on a Windows machine, you will already have a machine name associated with
+#it that will utilize an AT&T domain such as "sbc.com". You may need to add your domain to this as a comma separated list depending
+#upon your particular machine domain. This property is commented out as cadi SHOULD find your machine name. With version 1.2.1 of cadi,
+#it appears to resolve Mac machine names as well, now. But, this can be somewhat inconsistent depending on your specific working envrironment.
+hostname=mywebserver.att.com
+
+#Setting csp_domain to PROD will allow for testing using your attuid and password through GLO.
+csp_domain=PROD
+csp_devl_localhost=true
+
+basic_realm=csp.att.com
+#basic_realm=aaf.att.com
+basic_warn=TRUE
+
+cadi_loglevel=WARN
+cadi_keyfile=target/swm/package/nix/dist_files/appl/inventory-ui-service/etc/keyfile
+
+# Configure AAF
+#These are dummy values add appropriate values required
+aaf_url=url
+
+#AJSC - MECHID
+#These are dummy values add appropriate values required
+aaf_id=dummyid@ajsc.att.com
+aaf_password=enc:277edqJCjT0RlUI3BtbDQa-3Ha-CQGd
+aaf_timeout=5000
+aaf_clean_interval=30000
+aaf_user_expires=5000
+aaf_high_count=1000
+
+
diff --git a/src/main/config/csp-cookie-filter.properties b/src/main/config/csp-cookie-filter.properties
new file mode 100644
index 0000000..e12109a
--- /dev/null
+++ b/src/main/config/csp-cookie-filter.properties
@@ -0,0 +1,18 @@
+# AT&T Global login page. This is the redirect URL
+# Production login page:
+# https://www.e-access.att.com/empsvcs/hrpinmgt/pagLogin/
+#
+# Test login page:
+# https://webtest.csp.att.com/empsvcs/hrpinmgt/pagLogin/
+global.login.url=https://www.e-access.att.com/empsvcs/hrpinmgt/pagLogin/
+
+# valid domains for open redirect
+redirect-domain=att.com,sbc.com,bls.com,cingular.net
+
+# MOTS ID of the application
+application.id=24153
+
+# Required by esGateKeeper. Valid values are:
+# DEVL - used during development
+# PROD - used in production
+gatekeeper.environment=PROD
\ No newline at end of file
diff --git a/src/main/config/es_sv_mappings.json b/src/main/config/es_sv_mappings.json
new file mode 100644
index 0000000..c964ca3
--- /dev/null
+++ b/src/main/config/es_sv_mappings.json
@@ -0,0 +1,36 @@
+{
+ "properties": {
+ "entityType": {
+ "type": "string",
+ "analyzer": "ngram_analyzer",
+ "search_analyzer": "ngram_analyzer"
+ },
+ "entityPrimaryKeyValue": {
+ "type": "string",
+ "index": "not_analyzed"
+ },
+ "searchTagIDs": {
+ "type": "string"
+ },
+ "searchTags": {
+ "type": "string",
+ "analyzer": "ngram_analyzer"
+ },
+ "perspectives" : {
+ "type": "string",
+ "index": "not_analyzed"
+ },
+ "crossEntityReferenceValues": {
+ "type": "string",
+ "analyzer": "ngram_analyzer"
+ },
+ "link": {
+ "type": "string",
+ "index": "not_analyzed"
+ },
+ "lastmodTimestamp": {
+ "type": "date",
+ "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||yyyy-MM-dd HH:mm:ss||MM/dd/yyyy||yyyyMMdd'T'HHmmssZ"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/config/es_sv_settings.json b/src/main/config/es_sv_settings.json
new file mode 100644
index 0000000..21a357c
--- /dev/null
+++ b/src/main/config/es_sv_settings.json
@@ -0,0 +1,36 @@
+{
+ "analysis": {
+ "filter": {
+ "ngram_filter": {
+ "type": "nGram",
+ "min_gram": 1,
+ "max_gram": 50,
+ "token_chars": [
+ "letter",
+ "digit",
+ "punctuation",
+ "symbol"
+ ]
+ }
+ },
+ "analyzer": {
+ "ngram_analyzer": {
+ "type": "custom",
+ "tokenizer": "whitespace",
+ "filter": [
+ "lowercase",
+ "asciifolding",
+ "ngram_filter"
+ ]
+ },
+ "whitespace_analyzer": {
+ "type": "custom",
+ "tokenizer": "whitespace",
+ "filter": [
+ "lowercase",
+ "asciifolding"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/config/runner-web.xml b/src/main/config/runner-web.xml
index 1c6ccdc..2e39e24 100644
--- a/src/main/config/runner-web.xml
+++ b/src/main/config/runner-web.xml
@@ -19,27 +19,22 @@
org.springframework.web.context.ContextLoaderListener
-
+
+
+ PortalRestAPIProxy
+ org.openecomp.portalsdk.core.onboarding.crossapi.PortalRestAPIProxy
+
+
+
+ LoginFilter
+ org.onap.aai.sparky.security.filter.LoginFilter
+
+
ManagementServlet
ajsc.ManagementServlet
-
-
- VisualizationServlet
- org.onap.aai.sparky.viewandinspect.servlet.VisualizationServlet
-
-
-
- ElasticSearchSynchronizerFilter
- org.onap.aai.sparky.synchronizer.filter.ElasticSearchSynchronizerFilter
-
-
-
- OxmModelLoaderFilter
- org.onap.aai.sparky.config.oxm.OxmModelLoaderFilter
-
-
+
WriteableRequestFilter
com.att.ajsc.csi.writeablerequestfilter.WriteableRequestFilter
@@ -59,11 +54,6 @@
ajsc.servlet.AjscCamelServlet
-
- SearchServlet
- org.onap.aai.sparky.viewandinspect.servlet.SearchServlet
-
-
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
@@ -74,16 +64,9 @@
org.springframework.web.servlet.DispatcherServlet
1
+
-
- PortalRestAPIProxy
- org.openecomp.portalsdk.core.onboarding.crossapi.PortalRestAPIProxy
-
-
-
-
-
+
diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile
index 1ab49ff..b77cf1c 100644
--- a/src/main/docker/Dockerfile
+++ b/src/main/docker/Dockerfile
@@ -15,10 +15,8 @@ RUN export JAVA_HOME
# Build up the deployment folder structure
RUN mkdir -p $MICRO_HOME
-copy swm/package/nix/dist_files/appl/sparky-be/1.1.0-SNAPSHOT/ $MICRO_HOME/
-RUN ls -la $MICRO_HOME/
-RUN mkdir -p $BIN_HOME
-COPY *.sh $BIN_HOME/
+copy swm/package/nix/dist_files/appl/inventory-ui-service/1.1.0-SNAPSHOT/ $MICRO_HOME/
+RUN ls -la $BIN_HOME/
RUN chmod 755 $BIN_HOME/*
RUN ln -s /logs $MICRO_HOME/logs
diff --git a/src/main/java/org/onap/aai/sparky/JaxrsEchoService.java b/src/main/java/org/onap/aai/sparky/JaxrsEchoService.java
index 8e7e0a2..f7ea619 100644
--- a/src/main/java/org/onap/aai/sparky/JaxrsEchoService.java
+++ b/src/main/java/org/onap/aai/sparky/JaxrsEchoService.java
@@ -22,14 +22,14 @@
*/
package org.onap.aai.sparky;
-import com.att.ajsc.beans.PropertiesMapBean;
-import com.att.ajsc.filemonitor.AJSCPropertiesMap;
-
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import com.att.ajsc.beans.PropertiesMapBean;
+import com.att.ajsc.filemonitor.AJSCPropertiesMap;
+
/**
* The Class JaxrsEchoService.
diff --git a/src/main/java/org/onap/aai/sparky/JaxrsUserService.java b/src/main/java/org/onap/aai/sparky/JaxrsUserService.java
new file mode 100644
index 0000000..dc7f5a4
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/JaxrsUserService.java
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+/**
+ * The Class JaxrsUserService.
+ */
+@Path("/user")
+public class JaxrsUserService {
+
+ private static final Map userIdToNameMap;
+
+ static {
+ userIdToNameMap = new HashMap();
+ userIdToNameMap.put("dw113c", "Doug Wait");
+ userIdToNameMap.put("so401q", "Stuart O'Day");
+ }
+
+ /**
+ * Lookup user.
+ *
+ * @param userId the user id
+ * @return the string
+ */
+ @GET
+ @Path("/{userId}")
+ @Produces("text/plain")
+ public String lookupUser(@PathParam("userId") String userId) {
+ String name = userIdToNameMap.get(userId);
+ return name != null ? name : "unknown id";
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/Test.java b/src/main/java/org/onap/aai/sparky/Test.java
new file mode 100644
index 0000000..6efca77
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/Test.java
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky;
+
+public class Test {
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateSummaryProcessor.java b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateSummaryProcessor.java
new file mode 100644
index 0000000..6d2ec6e
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateSummaryProcessor.java
@@ -0,0 +1,238 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregatevnf.search;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.json.JsonObject;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.restlet.RestletConstants;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.dal.elasticsearch.SearchAdapter;
+import org.onap.aai.sparky.dataintegrity.config.DiUiConstants;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.search.filters.FilterQueryBuilder;
+import org.onap.aai.sparky.search.filters.entity.SearchFilter;
+import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+
+public class AggregateSummaryProcessor {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(AggregateSummaryProcessor.class);
+
+ private static final String KEY_FILTERS = "filters";
+
+ private SearchAdapter search = null;
+
+ private String vnfAggregationIndexName;
+ private String elasticSearchIp;
+ private String elatsticSearchPort;
+
+ public AggregateSummaryProcessor() {
+ try {
+ if (search == null) {
+ search = new SearchAdapter();
+ }
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "Failed to get elastic search configuration with error = " + exc.getMessage());
+ }
+ }
+
+ public void setVnfAggregationIndexName(String vnfAggregationIndexName) {
+ this.vnfAggregationIndexName = vnfAggregationIndexName;
+ }
+
+ public void setElasticSearchIp(String elasticSearchIp) {
+ this.elasticSearchIp = elasticSearchIp;
+ }
+
+ public void setElatsticSearchPort(String elatsticSearchPort) {
+ this.elatsticSearchPort = elatsticSearchPort;
+ }
+
+ public void getFilteredAggregation(Exchange exchange) {
+
+ Response response =
+ exchange.getIn().getHeader(RestletConstants.RESTLET_RESPONSE, Response.class);
+
+ Request request = exchange.getIn().getHeader(RestletConstants.RESTLET_REQUEST, Request.class);
+
+ /*
+ * Disables automatic Apache Camel Restlet component logging which prints out an undesirable log
+ * entry which includes client (e.g. browser) information
+ */
+ request.setLoggable(false);
+
+ try {
+ String payload = exchange.getIn().getBody(String.class);
+
+ if (payload == null || payload.isEmpty()) {
+
+ LOG.error(AaiUiMsgs.SEARCH_SERVLET_ERROR, "Request Payload is empty");
+
+ /*
+ * Don't throw back an error, just return an empty set
+ */
+
+ } else {
+
+ JSONObject parameters = new JSONObject(payload);
+
+ JSONArray requestFilters = null;
+ if (parameters.has(KEY_FILTERS)) {
+ requestFilters = parameters.getJSONArray(KEY_FILTERS);
+ } else {
+
+ JSONObject zeroResponsePayload = new JSONObject();
+ zeroResponsePayload.put("count", 0);
+ response.setStatus(Status.SUCCESS_OK);
+ response.setEntity(zeroResponsePayload.toString(), MediaType.APPLICATION_JSON);
+ exchange.getOut().setBody(response);
+
+ LOG.error(AaiUiMsgs.ERROR_FILTERS_NOT_FOUND);
+ return;
+ }
+
+ if (requestFilters != null && requestFilters.length() > 0) {
+ List filtersToQuery = new ArrayList();
+ for (int i = 0; i < requestFilters.length(); i++) {
+ JSONObject filterEntry = requestFilters.getJSONObject(i);
+ filtersToQuery.add(filterEntry);
+ }
+
+ String jsonResponsePayload = getVnfFilterAggregations(filtersToQuery);
+ response.setStatus(Status.SUCCESS_OK);
+ response.setEntity(jsonResponsePayload, MediaType.APPLICATION_JSON);
+ exchange.getOut().setBody(response);
+
+ } else {
+ String emptyResponse = getEmptyAggResponse();
+ response.setStatus(Status.SUCCESS_OK);
+ response.setEntity(emptyResponse, MediaType.APPLICATION_JSON);
+ exchange.getOut().setBody(response);
+ LOG.error(AaiUiMsgs.ERROR_FILTERS_NOT_FOUND);
+ }
+ }
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "FilterProcessor failed to get filter list due to error = " + exc.getMessage());
+ }
+ }
+
+ private String getEmptyAggResponse() {
+ JSONObject aggPayload = new JSONObject();
+ aggPayload.put("totalChartHits", 0);
+ aggPayload.put("buckets", new JSONArray());
+ JSONObject payload = new JSONObject();
+ payload.append("groupby_aggregation", aggPayload);
+
+ return payload.toString();
+ }
+
+ private static final String FILTER_ID_KEY = "filterId";
+ private static final String FILTER_VALUE_KEY = "filterValue";
+ private static final int DEFAULT_SHOULD_MATCH_SCORE = 1;
+ private static final String VNF_FILTER_AGGREGATION = "vnfFilterAggregation";
+
+
+ private String getVnfFilterAggregations(List filtersToQuery) throws IOException {
+
+ List searchFilters = new ArrayList();
+ for (JSONObject filterEntry : filtersToQuery) {
+
+ String filterId = filterEntry.getString(FILTER_ID_KEY);
+ if (filterId != null) {
+ SearchFilter filter = new SearchFilter();
+ filter.setFilterId(filterId);
+
+ if (filterEntry.has(FILTER_VALUE_KEY)) {
+ String filterValue = filterEntry.getString(FILTER_VALUE_KEY);
+ filter.addValue(filterValue);
+ }
+
+ searchFilters.add(filter);
+ }
+ }
+
+ // Create query for summary by entity type
+ JsonObject vnfSearch =
+ FilterQueryBuilder.createCombinedBoolAndAggQuery(searchFilters, DEFAULT_SHOULD_MATCH_SCORE);
+
+ // Parse response for summary by entity type query
+ OperationResult opResult =
+ search.doPost(getFullUrl(vnfAggregationIndexName, TierSupportUiConstants.ES_SEARCH_API),
+ vnfSearch.toString(), DiUiConstants.APP_JSON);
+
+ return buildAggregateVnfResponseJson(opResult.getResult());
+
+ }
+
+ /**
+ * Get Full URL for search using elastic search configuration.
+ *
+ * @param api the api
+ * @return the full url
+ */
+ private String getFullUrl(String indexName, String api) {
+ final String host = elasticSearchIp;
+ final String port = elatsticSearchPort;
+ return String.format("http://%s:%s/%s/%s", host, port, indexName, api);
+ }
+
+ private String buildAggregateVnfResponseJson(String responseJsonStr) {
+
+ JSONObject finalOutputToFe = new JSONObject();
+ JSONObject responseJson = new JSONObject(responseJsonStr);
+
+
+ JSONObject hits = responseJson.getJSONObject("hits");
+ int totalHits = hits.getInt("total");
+ finalOutputToFe.put("total", totalHits);
+
+ JSONObject aggregations = responseJson.getJSONObject("aggregations");
+ String[] aggKeys = JSONObject.getNames(aggregations);
+ JSONObject aggregationsList = new JSONObject();
+
+ for (String aggName : aggKeys) {
+ JSONObject aggregation = aggregations.getJSONObject(aggName);
+ JSONArray buckets = aggregation.getJSONArray("buckets");
+ aggregationsList.put(aggName, buckets);
+ }
+
+ finalOutputToFe.put("aggregations", aggregationsList);
+
+ return finalOutputToFe.toString();
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProvider.java b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProvider.java
new file mode 100644
index 0000000..ec3dfaa
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProvider.java
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregatevnf.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.json.JsonObject;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.common.search.CommonSearchSuggestion;
+import org.onap.aai.sparky.dal.elasticsearch.SearchAdapter;
+import org.onap.aai.sparky.dataintegrity.config.DiUiConstants;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.search.api.SearchProvider;
+import org.onap.aai.sparky.search.entity.QuerySearchEntity;
+import org.onap.aai.sparky.search.entity.SearchSuggestion;
+import org.onap.aai.sparky.search.filters.entity.UiFilterValueEntity;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class AggregateVnfSearchProvider implements SearchProvider {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(AggregateVnfSearchProvider.class);
+
+ private ObjectMapper mapper;
+ private static SearchAdapter search = null;
+
+ private String autoSuggestIndexName;
+ private String elasticSearchIp;
+ private String elatsticSearchPort;
+
+ public AggregateVnfSearchProvider() {
+
+ mapper = new ObjectMapper();
+
+ try {
+ if (search == null) {
+ search = new SearchAdapter();
+ }
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.CONFIGURATION_ERROR,
+ "Search Configuration Error. Error = " + exc.getMessage());
+ }
+ }
+
+ public void setAutoSuggestIndexName(String autoSuggestIndexName) {
+ this.autoSuggestIndexName = autoSuggestIndexName;
+ }
+
+ public void setElasticSearchIp(String elasticSearchIp) {
+ this.elasticSearchIp = elasticSearchIp;
+ }
+
+ public void setElatsticSearchPort(String elatsticSearchPort) {
+ this.elatsticSearchPort = elatsticSearchPort;
+ }
+
+ /**
+ * Get Full URL for search using elastic search configuration.
+ *
+ * @param api the api
+ * @return the full url
+ */
+ private String getFullUrl(String indexName, String api) {
+ final String host = elasticSearchIp;
+ final String port = elatsticSearchPort;
+ return String.format("http://%s:%s/%s/%s", host, port, indexName, api);
+ }
+
+ @Override
+ public List search(QuerySearchEntity queryRequest) {
+
+ List returnList = new ArrayList();
+
+ try {
+
+ /* Create suggestions query */
+ JsonObject vnfSearch = VnfSearchQueryBuilder.createSuggestionsQuery(
+ String.valueOf(queryRequest.getMaxResults()), queryRequest.getQueryStr());
+
+ /* Parse suggestions response */
+ OperationResult opResult =
+ search.doPost(getFullUrl(autoSuggestIndexName, TierSupportUiConstants.ES_SUGGEST_API),
+ vnfSearch.toString(), DiUiConstants.APP_JSON);
+
+ String result = opResult.getResult();
+
+ if (!opResult.wasSuccessful()) {
+ LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
+ return returnList;
+ }
+
+ JSONObject responseJson = new JSONObject(result);
+ String suggestionsKey = "vnfs";
+ JSONArray suggestionsArray = new JSONArray();
+ JSONArray suggestions = responseJson.getJSONArray(suggestionsKey);
+ if (suggestions.length() > 0) {
+ suggestionsArray = suggestions.getJSONObject(0).getJSONArray("options");
+ for (int i = 0; i < suggestionsArray.length(); i++) {
+ JSONObject querySuggestion = suggestionsArray.getJSONObject(i);
+ if (querySuggestion != null) {
+ CommonSearchSuggestion responseSuggestion = new CommonSearchSuggestion();
+ responseSuggestion.setText(querySuggestion.getString("text"));
+ responseSuggestion.setRoute("vnfSearch"); // TODO -> Read route from
+ // suggestive-search.properties instead of
+ // hard coding
+ responseSuggestion
+ .setHashId(NodeUtils.generateUniqueShaDigest(querySuggestion.getString("text")));
+
+ // Extract filter list from JSON and add to response suggestion
+ JSONObject payload = querySuggestion.getJSONObject("payload");
+ if (payload.length() > 0) {
+ JSONArray filterList = payload.getJSONArray("filterList");
+ for (int filter = 0; filter < filterList.length(); filter++) {
+ String filterValueString = filterList.getJSONObject(filter).toString();
+ UiFilterValueEntity filterValue =
+ mapper.readValue(filterValueString, UiFilterValueEntity.class);
+ responseSuggestion.getFilterValues().add(filterValue);
+ }
+ }
+ returnList.add(responseSuggestion);
+ }
+ }
+ }
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, "Search failed due to error = " + exc.getMessage());
+ }
+
+ return returnList;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregatevnf/search/VnfSearchQueryBuilder.java b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/VnfSearchQueryBuilder.java
new file mode 100644
index 0000000..96fea3f
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregatevnf/search/VnfSearchQueryBuilder.java
@@ -0,0 +1,184 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregatevnf.search;
+
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+
+import org.onap.aai.sparky.dataintegrity.config.DiUiConstants;
+
+/**
+ * Build a JSON payload to send to elastic search to get vnf search data.
+ */
+
+public class VnfSearchQueryBuilder {
+ static final String SEVERITY = DiUiConstants.SEVERITY;
+ static final String TIMESTAMP = DiUiConstants.KEY_TIMESTAMP;
+ static final String VIOLATIONS = DiUiConstants.VIOLATIONS;
+ static final String CATEGORY = DiUiConstants.CATEGORY;
+ static final String ENTITY_TYPE = DiUiConstants.ENTITY_TYPE;
+
+ static final String ITEM = DiUiConstants.KEY_ITEM;
+ static final String ITEM_AGG = DiUiConstants.KEY_ITEM_AGG;
+ static final String BY_ITEM = DiUiConstants.KEY_BY_ITEM;
+ static final String BUCKETS = DiUiConstants.KEY_BUCKETS;
+
+ /**
+ * Creates the suggestions query.
+ *
+ * @param maxResults maximum number of suggestions to fetch
+ * @param queryStr query string
+ * @return the json object
+ */
+
+ /*
+ * { "vnfs" : { "text" : "VNFs", "completion" : { "field" : "entity_suggest", "size": 1 } } }
+ */
+ public static JsonObject createSuggestionsQuery(String maxResults, String queryStr) {
+ JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
+
+ JsonObjectBuilder completionBlob = Json.createObjectBuilder();
+ completionBlob.add("field", "entity_suggest");
+ completionBlob.add("size", maxResults);
+
+ JsonObjectBuilder jsonAllBuilder = Json.createObjectBuilder();
+ jsonAllBuilder.add("text", queryStr);
+ jsonAllBuilder.add("completion", completionBlob);
+
+ jsonBuilder.add("vnfs", jsonAllBuilder.build());
+ return jsonBuilder.build();
+ }
+
+ public static JsonObject getTermBlob(String key, String value) {
+ JsonObjectBuilder termBlobBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder jsonBuilder = Json.createObjectBuilder().add(key, value);
+ return termBlobBuilder.add("term", jsonBuilder.build()).build();
+ }
+
+ public static void getSummaryAggsBlob(JsonObjectBuilder aggsBlobBuilder, String aggsKey,
+ int resultSize) {
+ JsonObjectBuilder fieldBuilder =
+ Json.createObjectBuilder().add("field", aggsKey).add("size", resultSize);
+ JsonObject aggsFieldBlob = fieldBuilder.build();
+ JsonObjectBuilder defaultBlobBuilder = Json.createObjectBuilder().add("terms", aggsFieldBlob);
+ JsonObject defaultBlob = defaultBlobBuilder.build();
+ aggsBlobBuilder.add("default", defaultBlob);
+ }
+
+ public static void buildSingleTermCountQuery(JsonObjectBuilder jsonBuilder, String key,
+ String value) {
+ jsonBuilder.add("query", getTermBlob(key, value));
+ }
+
+ public static void buildSingleTermSummaryQuery(JsonObjectBuilder jsonBuilder, String key,
+ String value, String groupByKey) {
+ JsonObjectBuilder queryBlobBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder aggsBlobBuilder = Json.createObjectBuilder();
+
+ queryBlobBuilder.add("constant_score",
+ Json.createObjectBuilder().add("filter", getTermBlob(key, value)));
+
+ getSummaryAggsBlob(aggsBlobBuilder, groupByKey, 0);
+
+ jsonBuilder.add("query", queryBlobBuilder.build());
+ jsonBuilder.add("aggs", aggsBlobBuilder.build());
+ }
+
+ public static void buildMultiTermSummaryQuery(JsonObjectBuilder jsonBuilder,
+ Map attributes, String groupByKey) {
+ JsonObjectBuilder queryBlobBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder aggsBlobBuilder = Json.createObjectBuilder();
+ JsonArrayBuilder mustBlobBuilder = Json.createArrayBuilder();
+ for (String key : attributes.keySet()) {
+ mustBlobBuilder.add(getTermBlob(key, attributes.get(key)));
+ }
+ JsonArray mustBlob = mustBlobBuilder.build();
+
+ queryBlobBuilder.add("constant_score", Json.createObjectBuilder().add("filter",
+ Json.createObjectBuilder().add("bool", Json.createObjectBuilder().add("must", mustBlob))));
+
+ getSummaryAggsBlob(aggsBlobBuilder, groupByKey, 0);
+
+ jsonBuilder.add("query", queryBlobBuilder.build());
+ jsonBuilder.add("aggs", aggsBlobBuilder.build());
+ }
+
+ public static void buildZeroTermSummaryQuery(JsonObjectBuilder jsonBuilder, String groupByKey) {
+ JsonObjectBuilder aggsBlobBuilder = Json.createObjectBuilder();
+
+ getSummaryAggsBlob(aggsBlobBuilder, groupByKey, 0);
+
+ jsonBuilder.add("aggs", aggsBlobBuilder.build());
+ }
+
+ public static void buildMultiTermCountQuery(JsonObjectBuilder jsonBuilder,
+ Map attributes) {
+ JsonArrayBuilder mustBlobBuilder = Json.createArrayBuilder();
+ for (String key : attributes.keySet()) {
+ mustBlobBuilder.add(getTermBlob(key, attributes.get(key)));
+ }
+ jsonBuilder.add("query", Json.createObjectBuilder().add("bool",
+ Json.createObjectBuilder().add("must", mustBlobBuilder)));
+ }
+
+
+
+ public static JsonObject createSummaryByEntityTypeQuery(Map attributes,
+ String groupByKey) {
+ JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
+ jsonBuilder.add("size", "0"); // avoid source data
+ if (attributes.size() == 0) {
+ buildZeroTermSummaryQuery(jsonBuilder, groupByKey);
+ } else if (attributes.size() == 1) {
+ Map.Entry entry = attributes.entrySet().iterator().next();
+ buildSingleTermSummaryQuery(jsonBuilder, entry.getKey(), entry.getValue(), groupByKey);
+ } else {
+ buildMultiTermSummaryQuery(jsonBuilder, attributes, groupByKey);
+ }
+ return jsonBuilder.build();
+ }
+
+ public static JsonObject createEntityCountsQuery(Map attributes) {
+ JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
+ if (attributes.size() == 1) {
+ Map.Entry entry = attributes.entrySet().iterator().next();
+ buildSingleTermCountQuery(jsonBuilder, entry.getKey(), entry.getValue());
+ } else {
+ buildMultiTermCountQuery(jsonBuilder, attributes);
+ }
+ return jsonBuilder.build();
+ }
+
+ public static JsonArray getSortCriteria(String sortFieldName, String sortOrder) {
+ JsonArrayBuilder jsonBuilder = Json.createArrayBuilder();
+ jsonBuilder.add(Json.createObjectBuilder().add(sortFieldName,
+ Json.createObjectBuilder().add("order", sortOrder)));
+
+ return jsonBuilder.build();
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSyncControllerFactory.java b/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSyncControllerFactory.java
new file mode 100644
index 0000000..6d8decf
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSyncControllerFactory.java
@@ -0,0 +1,232 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregation.sync;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+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.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.ElasticSearchIndexCleaner;
+import org.onap.aai.sparky.sync.ElasticSearchSchemaFactory;
+import org.onap.aai.sparky.sync.IndexCleaner;
+import org.onap.aai.sparky.sync.IndexIntegrityValidator;
+import org.onap.aai.sparky.sync.SyncController;
+import org.onap.aai.sparky.sync.SyncControllerImpl;
+import org.onap.aai.sparky.sync.SyncControllerRegistrar;
+import org.onap.aai.sparky.sync.SyncControllerRegistry;
+import org.onap.aai.sparky.sync.config.ElasticSearchEndpointConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.config.SyncControllerConfig;
+
+public class AggregationSyncControllerFactory implements SyncControllerRegistrar {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(AggregationSyncControllerFactory.class);
+
+ private ActiveInventoryAdapter aaiAdapter;
+ private ElasticSearchAdapter esAdapter;
+ private SuggestionEntityLookup suggestionEntityLookup;
+
+ private Map aggregationEntityToIndexMap;
+ private Map indexNameToSchemaConfigMap;
+
+ private ElasticSearchEndpointConfig elasticSearchEndpointConfig;
+ private SyncControllerConfig syncControllerConfig;
+ private SyncControllerRegistry syncControllerRegistry;
+ private NetworkStatisticsConfig aaiStatConfig;
+ private NetworkStatisticsConfig esStatConfig;
+
+ private List syncControllers;
+
+ public AggregationSyncControllerFactory(ElasticSearchEndpointConfig esEndpointConfig,
+ SyncControllerConfig syncControllerConfig, SyncControllerRegistry syncControllerRegistry,
+ SuggestionEntityLookup suggestionEntityLookup) {
+ this.syncControllers = new ArrayList();
+ this.elasticSearchEndpointConfig = esEndpointConfig;
+ this.syncControllerConfig = syncControllerConfig;
+ this.syncControllerRegistry = syncControllerRegistry;
+ this.suggestionEntityLookup = suggestionEntityLookup;
+ }
+
+ public NetworkStatisticsConfig getAaiStatConfig() {
+ return aaiStatConfig;
+ }
+
+ public void setAaiStatConfig(NetworkStatisticsConfig aaiStatConfig) {
+ this.aaiStatConfig = aaiStatConfig;
+ }
+
+ public NetworkStatisticsConfig getEsStatConfig() {
+ return esStatConfig;
+ }
+
+ public void setEsStatConfig(NetworkStatisticsConfig esStatConfig) {
+ this.esStatConfig = esStatConfig;
+ }
+
+ public Map getIndexNameToSchemaConfigMap() {
+ return indexNameToSchemaConfigMap;
+ }
+
+ public void setIndexNameToSchemaConfigMap(
+ Map indexNameToSchemaConfigMap) {
+ this.indexNameToSchemaConfigMap = indexNameToSchemaConfigMap;
+ }
+
+ public ElasticSearchEndpointConfig getElasticSearchEndpointConfig() {
+ return elasticSearchEndpointConfig;
+ }
+
+ public void setElasticSearchEndpointConfig(
+ ElasticSearchEndpointConfig elasticSearchEndpointConfig) {
+ this.elasticSearchEndpointConfig = elasticSearchEndpointConfig;
+ }
+
+ public SyncControllerConfig getSyncControllerConfig() {
+ return syncControllerConfig;
+ }
+
+ public void setSyncControllerConfig(SyncControllerConfig syncControllerConfig) {
+ this.syncControllerConfig = syncControllerConfig;
+ }
+
+ public ActiveInventoryAdapter getAaiAdapter() {
+ return aaiAdapter;
+ }
+
+ public void setAaiAdapter(ActiveInventoryAdapter aaiAdapter) {
+ this.aaiAdapter = aaiAdapter;
+ }
+
+ public ElasticSearchAdapter getEsAdapter() {
+ return esAdapter;
+ }
+
+ public void setEsAdapter(ElasticSearchAdapter esAdapter) {
+ this.esAdapter = esAdapter;
+ }
+
+ public SuggestionEntityLookup getSuggestionEntityLookup() {
+ return suggestionEntityLookup;
+ }
+
+ public void setSuggestionEntityLookup(SuggestionEntityLookup suggestionEntityLookup) {
+ this.suggestionEntityLookup = suggestionEntityLookup;
+ }
+
+ public Map getAggregationEntityToIndexMap() {
+ return aggregationEntityToIndexMap;
+ }
+
+ public void setAggregationEntityToIndexMap(Map aggregationEntityToIndexMap) {
+ this.aggregationEntityToIndexMap = aggregationEntityToIndexMap;
+ }
+
+ public void buildControllers() {
+
+ if (syncControllerConfig.isEnabled()) {
+
+ Map suggestionEntitites =
+ suggestionEntityLookup.getSuggestionSearchEntityDescriptors();
+ SyncControllerImpl aggregationSyncController = null;
+
+ for (String entityType : suggestionEntitites.keySet()) {
+
+ String indexName = aggregationEntityToIndexMap.get(entityType);
+
+ if (indexName == null) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "Could not determine aggregation index name" + " for entity type: " + entityType);
+ continue;
+ }
+
+ try {
+
+ aggregationSyncController = new SyncControllerImpl(syncControllerConfig, entityType);
+
+ ElasticSearchSchemaConfig schemaConfig = indexNameToSchemaConfigMap.get(indexName);
+
+ if (schemaConfig == null) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "Could not determine elastic search schema config for index name: " + indexName);
+ continue;
+ }
+
+ IndexIntegrityValidator aggregationIndexValidator =
+ new IndexIntegrityValidator(esAdapter, schemaConfig, elasticSearchEndpointConfig,
+ ElasticSearchSchemaFactory.getIndexSchema(schemaConfig));
+
+ aggregationSyncController.registerIndexValidator(aggregationIndexValidator);
+
+ AggregationSynchronizer aggSynchronizer = new AggregationSynchronizer(entityType,
+ schemaConfig, syncControllerConfig.getNumInternalSyncWorkers(),
+ syncControllerConfig.getNumSyncActiveInventoryWorkers(),
+ syncControllerConfig.getNumSyncElasticWorkers(), aaiStatConfig, esStatConfig);
+
+ aggSynchronizer.setAaiAdapter(aaiAdapter);
+ aggSynchronizer.setElasticSearchAdapter(esAdapter);
+
+ aggregationSyncController.registerEntitySynchronizer(aggSynchronizer);
+
+ IndexCleaner entityDataIndexCleaner =
+ new ElasticSearchIndexCleaner(esAdapter, elasticSearchEndpointConfig, schemaConfig);
+
+ aggregationSyncController.registerIndexCleaner(entityDataIndexCleaner);
+
+ syncControllers.add(aggregationSyncController);
+ } catch (Exception exc) {
+
+ exc.printStackTrace();
+
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "Failed to build aggregation sync controller. Error : " + exc.getMessage());
+ }
+
+ }
+ } else {
+ LOG.info(AaiUiMsgs.INFO_GENERIC, "Sync controller with name = "
+ + syncControllerConfig.getControllerName() + " is disabled");
+ }
+ }
+
+ @Override
+ public void registerController() {
+
+ buildControllers();
+
+ if (syncControllerRegistry != null) {
+ for (SyncController controller : syncControllers) {
+ syncControllerRegistry.registerSyncController(controller);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSynchronizer.java b/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSynchronizer.java
new file mode 100644
index 0000000..2a115db
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregation/sync/AggregationSynchronizer.java
@@ -0,0 +1,778 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregation.sync;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+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.OxmEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
+import org.onap.aai.sparky.dal.NetworkTransaction;
+import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
+import org.onap.aai.sparky.dal.elasticsearch.config.ElasticSearchConfig;
+import org.onap.aai.sparky.dal.rest.HttpMethod;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.AbstractEntitySynchronizer;
+import org.onap.aai.sparky.sync.IndexSynchronizer;
+import org.onap.aai.sparky.sync.SynchronizerConstants;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.entity.AggregationEntity;
+import org.onap.aai.sparky.sync.entity.MergableEntity;
+import org.onap.aai.sparky.sync.entity.SelfLinkDescriptor;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.sync.enumeration.SynchronizerState;
+import org.onap.aai.sparky.sync.task.PerformActiveInventoryRetrieval;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchPut;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchRetrieval;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchUpdate;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * The Class AutosuggestionSynchronizer.
+ */
+public class AggregationSynchronizer extends AbstractEntitySynchronizer
+ implements IndexSynchronizer {
+
+ /**
+ * The Class RetryAggregationEntitySyncContainer.
+ */
+ private class RetryAggregationEntitySyncContainer {
+ NetworkTransaction txn;
+ AggregationEntity ae;
+
+ /**
+ * Instantiates a new retry aggregation entity sync container.
+ *
+ * @param txn the txn
+ * @param ae the se
+ */
+ public RetryAggregationEntitySyncContainer(NetworkTransaction txn, AggregationEntity ae) {
+ this.txn = txn;
+ this.ae = ae;
+ }
+
+ public NetworkTransaction getNetworkTransaction() {
+ return txn;
+ }
+
+ public AggregationEntity getAggregationEntity() {
+ return ae;
+ }
+ }
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(AggregationSynchronizer.class);
+ private static final String INSERTION_DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmssZ";
+
+ private boolean allWorkEnumerated;
+ private Deque selflinks;
+ private Deque retryQueue;
+ private Map retryLimitTracker;
+ protected ExecutorService esPutExecutor;
+ private ConcurrentHashMap entityCounters;
+ private boolean syncInProgress;
+ private Map contextMap;
+ private String entityType;
+ private ElasticSearchSchemaConfig schemaConfig;
+
+ /**
+ * Instantiates a new entity aggregation synchronizer.
+ *
+ * @param indexName the index name
+ * @throws Exception the exception
+ */
+ public AggregationSynchronizer(String entityType, ElasticSearchSchemaConfig schemaConfig,
+ int numSyncWorkers, int numActiveInventoryWorkers, int numElasticWorkers,
+ NetworkStatisticsConfig aaiStatConfig, NetworkStatisticsConfig esStatConfig)
+ throws Exception {
+
+ super(LOG, "AGGES-" + schemaConfig.getIndexName().toUpperCase(), numSyncWorkers,
+ numActiveInventoryWorkers, numElasticWorkers, schemaConfig.getIndexName(), aaiStatConfig,
+ esStatConfig); // multiple
+ // Autosuggestion
+ // Entity Synchronizer will
+ // run for different indices
+
+ this.schemaConfig = schemaConfig;
+ this.entityType = entityType;
+ this.allWorkEnumerated = false;
+ this.entityCounters = new ConcurrentHashMap();
+ this.synchronizerName = "Entity Aggregation Synchronizer";
+ this.enabledStatFlags = EnumSet.of(StatFlag.AAI_REST_STATS, StatFlag.ES_REST_STATS);
+ this.syncInProgress = false;
+ this.allWorkEnumerated = false;
+ this.selflinks = new ConcurrentLinkedDeque();
+ this.retryQueue = new ConcurrentLinkedDeque();
+ this.retryLimitTracker = new ConcurrentHashMap();
+
+ this.esPutExecutor = NodeUtils.createNamedExecutor("AGGES-ES-PUT", 1, LOG);
+
+ this.aaiEntityStats.intializeEntityCounters(entityType);
+ this.esEntityStats.intializeEntityCounters(entityType);
+
+ this.contextMap = MDC.getCopyOfContextMap();
+ }
+
+ /**
+ * Collect all the work.
+ *
+ * @return the operation state
+ */
+ private OperationState collectAllTheWork() {
+ final Map contextMap = MDC.getCopyOfContextMap();
+ final String entity = this.getEntityType();
+ try {
+
+ aaiWorkOnHand.set(1);
+
+ supplyAsync(new Supplier() {
+
+ @Override
+ public Void get() {
+ MDC.setContextMap(contextMap);
+ OperationResult typeLinksResult = null;
+ try {
+ typeLinksResult = aaiAdapter.getSelfLinksByEntityType(entity);
+ aaiWorkOnHand.decrementAndGet();
+ processEntityTypeSelfLinks(typeLinksResult);
+ } catch (Exception exc) {
+ // TODO -> LOG, what should be logged here?
+
+ exc.printStackTrace();
+ }
+
+ return null;
+ }
+
+ }, aaiExecutor).whenComplete((result, error) -> {
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "An error occurred getting data from AAI. Error = " + error.getMessage());
+ }
+ });
+
+ while (aaiWorkOnHand.get() != 0) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.WAIT_FOR_ALL_SELFLINKS_TO_BE_COLLECTED);
+ }
+
+ Thread.sleep(1000);
+ }
+
+ aaiWorkOnHand.set(selflinks.size());
+ allWorkEnumerated = true;
+ syncEntityTypes();
+
+ while (!isSyncDone()) {
+ performRetrySync();
+ Thread.sleep(1000);
+ }
+
+ /*
+ * Make sure we don't hang on to retries that failed which could cause issues during future
+ * syncs
+ */
+ retryLimitTracker.clear();
+
+ } catch (Exception exc) {
+ // TODO -> LOG, waht should be logged here?
+ }
+
+ return OperationState.OK;
+ }
+
+
+ /**
+ * Perform retry sync.
+ */
+ private void performRetrySync() {
+ while (retryQueue.peek() != null) {
+
+ RetryAggregationEntitySyncContainer rsc = retryQueue.poll();
+ if (rsc != null) {
+
+ AggregationEntity ae = rsc.getAggregationEntity();
+ NetworkTransaction txn = rsc.getNetworkTransaction();
+
+ String link = null;
+ try {
+ /*
+ * In this retry flow the se object has already derived its fields
+ */
+ link = getElasticFullUrl("/" + ae.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_FAILED_TO_CONSTRUCT_URI, exc.getLocalizedMessage());
+ }
+
+ if (link != null) {
+ NetworkTransaction retryTransaction = new NetworkTransaction();
+ retryTransaction.setLink(link);
+ retryTransaction.setEntityType(txn.getEntityType());
+ retryTransaction.setDescriptor(txn.getDescriptor());
+ retryTransaction.setOperationType(HttpMethod.GET);
+
+ /*
+ * IMPORTANT - DO NOT incrementAndGet the esWorkOnHand as this is a retry flow! We already
+ * called incrementAndGet when queuing the failed PUT!
+ */
+
+ supplyAsync(new PerformElasticSearchRetrieval(retryTransaction, elasticSearchAdapter),
+ esExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ES_RETRIEVAL_FAILED_RESYNC, error.getLocalizedMessage());
+ } else {
+ updateElasticSearchCounters(result);
+ performDocumentUpsert(result, ae);
+ }
+ });
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Perform document upsert.
+ *
+ * @param esGetTxn the es get txn
+ * @param ae the ae
+ */
+ protected void performDocumentUpsert(NetworkTransaction esGetTxn, AggregationEntity ae) {
+ /**
+ *
+ *
+ * As part of the response processing we need to do the following:
+ * - 1. Extract the version (if present), it will be the ETAG when we use the
+ * Search-Abstraction-Service
+ *
- 2. Spawn next task which is to do the PUT operation into elastic with or with the version
+ * tag
+ *
- a) if version is null or RC=404, then standard put, no _update with version tag
+ *
- b) if version != null, do PUT with _update?version= versionNumber in the URI to elastic
+ *
+ *
+ */
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + ae.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_LINK_UPSERT, exc.getLocalizedMessage());
+ return;
+ }
+
+ String versionNumber = null;
+ boolean wasEntryDiscovered = false;
+ if (esGetTxn.getOperationResult().getResultCode() == 404) {
+ LOG.info(AaiUiMsgs.ES_SIMPLE_PUT, ae.getEntityPrimaryKeyValue());
+ } else if (esGetTxn.getOperationResult().getResultCode() == 200) {
+ wasEntryDiscovered = true;
+ try {
+ versionNumber = NodeUtils.extractFieldValueFromObject(
+ NodeUtils.convertJsonStrToJsonNode(esGetTxn.getOperationResult().getResult()),
+ "_version");
+ } catch (IOException exc) {
+ String message =
+ "Error extracting version number from response, aborting aggregation entity sync of "
+ + ae.getEntityPrimaryKeyValue() + ". Error - " + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ERROR_EXTRACTING_FROM_RESPONSE, message);
+ return;
+ }
+ } else {
+ /*
+ * Not being a 200 does not mean a failure. eg 201 is returned for created. TODO -> Should we
+ * return.
+ */
+ LOG.error(AaiUiMsgs.ES_OPERATION_RETURN_CODE,
+ String.valueOf(esGetTxn.getOperationResult().getResultCode()));
+ return;
+ }
+
+ try {
+ String jsonPayload = null;
+ if (wasEntryDiscovered) {
+ try {
+ ArrayList sourceObject = new ArrayList();
+ NodeUtils.extractObjectsByKey(
+ NodeUtils.convertJsonStrToJsonNode(esGetTxn.getOperationResult().getResult()),
+ "_source", sourceObject);
+
+ if (!sourceObject.isEmpty()) {
+ String responseSource = NodeUtils.convertObjectToJson(sourceObject.get(0), false);
+ MergableEntity me = mapper.readValue(responseSource, MergableEntity.class);
+ ObjectReader updater = mapper.readerForUpdating(me);
+ MergableEntity merged = updater.readValue(ae.getAsJson());
+ jsonPayload = mapper.writeValueAsString(merged);
+ }
+ } catch (IOException exc) {
+ String message =
+ "Error extracting source value from response, aborting aggregation entity sync of "
+ + ae.getEntityPrimaryKeyValue() + ". Error - " + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ERROR_EXTRACTING_FROM_RESPONSE, message);
+ return;
+ }
+ } else {
+ jsonPayload = ae.getAsJson();
+ }
+
+ if (wasEntryDiscovered) {
+ if (versionNumber != null && jsonPayload != null) {
+
+ String requestPayload =
+ elasticSearchAdapter.buildBulkImportOperationRequest(schemaConfig.getIndexName(),
+ schemaConfig.getIndexDocType(), ae.getId(), versionNumber, jsonPayload);
+
+ NetworkTransaction transactionTracker = new NetworkTransaction();
+ transactionTracker.setEntityType(esGetTxn.getEntityType());
+ transactionTracker.setDescriptor(esGetTxn.getDescriptor());
+ transactionTracker.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ supplyAsync(new PerformElasticSearchUpdate(ElasticSearchConfig.getConfig().getBulkUrl(),
+ requestPayload, elasticSearchAdapter, transactionTracker), esPutExecutor)
+ .whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ String message = "Aggregation entity sync UPDATE PUT error - "
+ + error.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ } else {
+ updateElasticSearchCounters(result);
+ processStoreDocumentResult(result, esGetTxn, ae);
+ }
+ });
+ }
+
+ } else {
+ if (link != null && jsonPayload != null) {
+
+ NetworkTransaction updateElasticTxn = new NetworkTransaction();
+ updateElasticTxn.setLink(link);
+ updateElasticTxn.setEntityType(esGetTxn.getEntityType());
+ updateElasticTxn.setDescriptor(esGetTxn.getDescriptor());
+ updateElasticTxn.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ supplyAsync(
+ new PerformElasticSearchPut(jsonPayload, updateElasticTxn, elasticSearchAdapter),
+ esPutExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ String message =
+ "Aggregation entity sync UPDATE PUT error - " + error.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ } else {
+ updateElasticSearchCounters(result);
+ processStoreDocumentResult(result, esGetTxn, ae);
+ }
+ });
+ }
+ }
+ } catch (Exception exc) {
+ String message = "Exception caught during aggregation entity sync PUT operation. Message - "
+ + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ }
+ }
+
+ /**
+ * Should allow retry.
+ *
+ * @param id the id
+ * @return true, if successful
+ */
+ private boolean shouldAllowRetry(String id) {
+ boolean isRetryAllowed = true;
+ if (retryLimitTracker.get(id) != null) {
+ Integer currentCount = retryLimitTracker.get(id);
+ if (currentCount.intValue() >= RETRY_COUNT_PER_ENTITY_LIMIT.intValue()) {
+ isRetryAllowed = false;
+ String message = "Aggregation entity re-sync limit reached for " + id
+ + ", re-sync will no longer be attempted for this entity";
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ } else {
+ Integer newCount = new Integer(currentCount.intValue() + 1);
+ retryLimitTracker.put(id, newCount);
+ }
+ } else {
+ Integer firstRetryCount = new Integer(1);
+ retryLimitTracker.put(id, firstRetryCount);
+ }
+
+ return isRetryAllowed;
+ }
+
+ /**
+ * Process store document result.
+ *
+ * @param esPutResult the es put result
+ * @param esGetResult the es get result
+ * @param ae the ae
+ */
+ private void processStoreDocumentResult(NetworkTransaction esPutResult,
+ NetworkTransaction esGetResult, AggregationEntity ae) {
+
+ OperationResult or = esPutResult.getOperationResult();
+
+ if (!or.wasSuccessful()) {
+ if (or.getResultCode() == VERSION_CONFLICT_EXCEPTION_CODE) {
+
+ if (shouldAllowRetry(ae.getId())) {
+ esWorkOnHand.incrementAndGet();
+
+ RetryAggregationEntitySyncContainer rsc =
+ new RetryAggregationEntitySyncContainer(esGetResult, ae);
+ retryQueue.push(rsc);
+
+ String message = "Store document failed during aggregation entity synchronization"
+ + " due to version conflict. Entity will be re-synced.";
+ LOG.warn(AaiUiMsgs.ERROR_GENERIC, message);
+ }
+ } else {
+ String message =
+ "Store document failed during aggregation entity synchronization with result code "
+ + or.getResultCode() + " and result message " + or.getResult();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ }
+ }
+ }
+
+ /**
+ * Sync entity types.
+ */
+ private void syncEntityTypes() {
+
+ while (selflinks.peek() != null) {
+
+ SelfLinkDescriptor linkDescriptor = selflinks.poll();
+ aaiWorkOnHand.decrementAndGet();
+
+ OxmEntityDescriptor descriptor = null;
+
+ if (linkDescriptor.getSelfLink() != null && linkDescriptor.getEntityType() != null) {
+
+ descriptor = OxmEntityLookup.getInstance().getEntityDescriptors()
+ .get(linkDescriptor.getEntityType());
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, linkDescriptor.getEntityType());
+ // go to next element in iterator
+ continue;
+ }
+
+ NetworkTransaction txn = new NetworkTransaction();
+ txn.setDescriptor(descriptor);
+ txn.setLink(linkDescriptor.getSelfLink());
+ txn.setOperationType(HttpMethod.GET);
+ txn.setEntityType(linkDescriptor.getEntityType());
+
+ aaiWorkOnHand.incrementAndGet();
+
+ supplyAsync(new PerformActiveInventoryRetrieval(txn, aaiAdapter), aaiExecutor)
+ .whenComplete((result, error) -> {
+
+ aaiWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.AAI_RETRIEVAL_FAILED_GENERIC, error.getLocalizedMessage());
+ } else {
+ if (result == null) {
+ LOG.error(AaiUiMsgs.AAI_RETRIEVAL_FAILED_FOR_SELF_LINK,
+ linkDescriptor.getSelfLink());
+ } else {
+ updateActiveInventoryCounters(result);
+ fetchDocumentForUpsert(result);
+ }
+ }
+ });
+ }
+
+ }
+
+ }
+
+ /**
+ * Fetch document for upsert.
+ *
+ * @param txn the txn
+ */
+ private void fetchDocumentForUpsert(NetworkTransaction txn) {
+ // modified
+ if (!txn.getOperationResult().wasSuccessful()) {
+ String message = "Self link failure. Result - " + txn.getOperationResult().getResult();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ return;
+ }
+
+ try {
+ final String jsonResult = txn.getOperationResult().getResult();
+ if (jsonResult != null && jsonResult.length() > 0) {
+
+ AggregationEntity ae = new AggregationEntity();
+ ae.setLink(ActiveInventoryConfig.extractResourcePath(txn.getLink()));
+ populateAggregationEntityDocument(ae, jsonResult, txn.getDescriptor());
+ ae.deriveFields();
+
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + ae.getId(), getIndexName());
+ } 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, ae);
+ }
+ });
+ }
+ }
+
+ } catch (JsonProcessingException exc) {
+ // TODO -> LOG, waht should be logged here?
+ } catch (IOException exc) {
+ // TODO -> LOG, waht should be logged here?
+ }
+ }
+
+
+ /**
+ * Populate aggregation entity document.
+ *
+ * @param doc the doc
+ * @param result the result
+ * @param resultDescriptor the result descriptor
+ * @throws JsonProcessingException the json processing exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ protected void populateAggregationEntityDocument(AggregationEntity doc, String result,
+ OxmEntityDescriptor resultDescriptor) throws JsonProcessingException, IOException {
+ doc.setEntityType(resultDescriptor.getEntityName());
+ JsonNode entityNode = mapper.readTree(result);
+ Map map = mapper.convertValue(entityNode, Map.class);
+ doc.copyAttributeKeyValuePair(map);
+ }
+
+ /**
+ * Process entity type self links.
+ *
+ * @param operationResult the operation result
+ */
+ private void processEntityTypeSelfLinks(OperationResult operationResult) {
+
+ JsonNode rootNode = null;
+
+ final String jsonResult = operationResult.getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0 && operationResult.wasSuccessful()) {
+
+ try {
+ rootNode = mapper.readTree(jsonResult);
+ } catch (IOException exc) {
+ String message = "Could not deserialize JSON (representing operation result) as node tree. "
+ + "Operation result = " + jsonResult + ". " + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.JSON_PROCESSING_ERROR, message);
+ }
+
+ JsonNode resultData = rootNode.get("result-data");
+ ArrayNode resultDataArrayNode = null;
+
+ if (resultData.isArray()) {
+ resultDataArrayNode = (ArrayNode) resultData;
+
+ Iterator elementIterator = resultDataArrayNode.elements();
+ JsonNode element = null;
+
+ while (elementIterator.hasNext()) {
+ element = elementIterator.next();
+
+ final String resourceType = NodeUtils.getNodeFieldAsText(element, "resource-type");
+ final String resourceLink = NodeUtils.getNodeFieldAsText(element, "resource-link");
+
+ OxmEntityDescriptor descriptor = null;
+
+ if (resourceType != null && resourceLink != null) {
+
+ descriptor = OxmEntityLookup.getInstance().getEntityDescriptors().get(resourceType);
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, resourceType);
+ // go to next element in iterator
+ continue;
+ }
+
+ selflinks.add(new SelfLinkDescriptor(resourceLink,
+ SynchronizerConstants.NODES_ONLY_MODIFIER, resourceType));
+
+
+ }
+ }
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#doSync()
+ */
+ @Override
+ public OperationState doSync() {
+ this.syncDurationInMs = -1;
+ syncStartedTimeStampInMs = System.currentTimeMillis();
+ String txnID = NodeUtils.getRandomTxnId();
+ MdcContext.initialize(txnID, "AggregationSynchronizer", "", "Sync", "");
+
+ return collectAllTheWork();
+ }
+
+ @Override
+ public SynchronizerState getState() {
+
+ if (!isSyncDone()) {
+ return SynchronizerState.PERFORMING_SYNCHRONIZATION;
+ }
+
+ return SynchronizerState.IDLE;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#getStatReport(boolean)
+ */
+ @Override
+ public String getStatReport(boolean showFinalReport) {
+ syncDurationInMs = System.currentTimeMillis() - syncStartedTimeStampInMs;
+ return getStatReport(syncDurationInMs, showFinalReport);
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public void setEntityType(String entityType) {
+ this.entityType = entityType;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ this.shutdownExecutors();
+ }
+
+ @Override
+ protected boolean isSyncDone() {
+
+ int totalWorkOnHand = aaiWorkOnHand.get() + esWorkOnHand.get();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC, indexName + ", isSyncDone(), totalWorkOnHand = "
+ + totalWorkOnHand + " all work enumerated = " + allWorkEnumerated);
+ }
+
+ if (totalWorkOnHand > 0 || !allWorkEnumerated) {
+ return false;
+ }
+
+ this.syncInProgress = false;
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.AbstractEntitySynchronizer#clearCache()
+ */
+ @Override
+ public void clearCache() {
+
+ if (syncInProgress) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
+ "Autosuggestion Entity Summarizer in progress, request to clear cache ignored");
+ return;
+ }
+
+ super.clearCache();
+ this.resetCounters();
+ if (entityCounters != null) {
+ entityCounters.clear();
+ }
+
+ allWorkEnumerated = false;
+
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySummarizer.java b/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySummarizer.java
new file mode 100644
index 0000000..5ee11be
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySummarizer.java
@@ -0,0 +1,391 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregation.sync;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+import javax.json.Json;
+import javax.ws.rs.core.MediaType;
+
+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.SearchableEntityLookup;
+import org.onap.aai.sparky.config.oxm.SearchableOxmEntityDescriptor;
+import org.onap.aai.sparky.dal.rest.HttpMethod;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.AbstractEntitySynchronizer;
+import org.onap.aai.sparky.sync.IndexSynchronizer;
+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.sync.enumeration.SynchronizerState;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * The Class HistoricalEntitySummarizer.
+ */
+public class HistoricalEntitySummarizer extends AbstractEntitySynchronizer
+ implements IndexSynchronizer {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(HistoricalEntitySummarizer.class);
+ private static final String INSERTION_DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmssZ";
+
+ private boolean allWorkEnumerated;
+ private ConcurrentHashMap entityCounters;
+ private boolean syncInProgress;
+ private Map contextMap;
+ private ElasticSearchSchemaConfig schemaConfig;
+
+ /**
+ * Instantiates a new historical entity summarizer.
+ *
+ * @param indexName the index name
+ * @throws Exception the exception
+ */
+ public HistoricalEntitySummarizer(ElasticSearchSchemaConfig schemaConfig, int internalSyncWorkers,
+ int aaiWorkers, int esWorkers, NetworkStatisticsConfig aaiStatConfig,
+ NetworkStatisticsConfig esStatConfig) throws Exception {
+ super(LOG, "HES", internalSyncWorkers, aaiWorkers, esWorkers, schemaConfig.getIndexName(),
+ aaiStatConfig, esStatConfig);
+
+ this.schemaConfig = schemaConfig;
+ this.allWorkEnumerated = false;
+ this.entityCounters = new ConcurrentHashMap();
+ this.synchronizerName = "Historical Entity Summarizer";
+ this.enabledStatFlags = EnumSet.of(StatFlag.AAI_REST_STATS, StatFlag.ES_REST_STATS);
+ this.syncInProgress = false;
+ this.contextMap = MDC.getCopyOfContextMap();
+ this.syncDurationInMs = -1;
+ }
+
+ /**
+ * Collect all the work.
+ *
+ * @return the operation state
+ */
+ private OperationState collectAllTheWork() {
+
+ Map descriptorMap =
+ SearchableEntityLookup.getInstance().getSearchableEntityDescriptors();
+
+ if (descriptorMap.isEmpty()) {
+ LOG.error(AaiUiMsgs.OXM_FAILED_RETRIEVAL, "historical entities");
+
+ return OperationState.ERROR;
+ }
+
+ Collection entityTypes = descriptorMap.keySet();
+
+ AtomicInteger asyncWoH = new AtomicInteger(0);
+
+ asyncWoH.set(entityTypes.size());
+
+ try {
+ for (String entityType : entityTypes) {
+
+ supplyAsync(new Supplier() {
+
+ @Override
+ public Void get() {
+ MDC.setContextMap(contextMap);
+ try {
+ OperationResult typeLinksResult = aaiAdapter.getSelfLinksByEntityType(entityType);
+ updateActiveInventoryCounters(HttpMethod.GET, entityType, typeLinksResult);
+ processEntityTypeSelfLinks(entityType, typeLinksResult);
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ERROR_GETTING_DATA_FROM_AAI, exc.getMessage());
+
+ }
+
+ return null;
+ }
+
+ }, aaiExecutor).whenComplete((result, error) -> {
+
+ asyncWoH.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.HISTORICAL_COLLECT_ERROR, error.getMessage());
+ }
+
+ });
+
+ }
+
+
+ while (asyncWoH.get() > 0) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
+ indexName + " summarizer waiting for all the links to be processed.");
+ }
+
+ Thread.sleep(250);
+ }
+
+ esWorkOnHand.set(entityCounters.size());
+
+ // start doing the real work
+ allWorkEnumerated = true;
+
+ insertEntityTypeCounters();
+
+ if (LOG.isDebugEnabled()) {
+
+ StringBuilder sb = new StringBuilder(128);
+
+ sb.append("\n\nHistorical Entity Counters:");
+
+ for (Entry entry : entityCounters.entrySet()) {
+ sb.append("\n").append(entry.getKey()).append(" = ").append(entry.getValue().get());
+ }
+
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC, sb.toString());
+
+ }
+
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.HISTORICAL_COLLECT_ERROR, exc.getMessage());
+
+
+ esWorkOnHand.set(0);
+ allWorkEnumerated = true;
+
+ return OperationState.ERROR;
+ }
+
+ return OperationState.OK;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#doSync()
+ */
+ @Override
+ public OperationState doSync() {
+ this.syncDurationInMs = -1;
+ String txnID = NodeUtils.getRandomTxnId();
+ MdcContext.initialize(txnID, "HistoricalEntitySynchronizer", "", "Sync", "");
+
+ if (syncInProgress) {
+ LOG.info(AaiUiMsgs.HISTORICAL_SYNC_PENDING);
+ return OperationState.PENDING;
+ }
+
+ clearCache();
+
+ syncInProgress = true;
+ this.syncStartedTimeStampInMs = System.currentTimeMillis();
+ allWorkEnumerated = false;
+
+ return collectAllTheWork();
+ }
+
+ /**
+ * Process entity type self links.
+ *
+ * @param entityType the entity type
+ * @param operationResult the operation result
+ */
+ private void processEntityTypeSelfLinks(String entityType, OperationResult operationResult) {
+
+ JsonNode rootNode = null;
+
+ final String jsonResult = operationResult.getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0 && operationResult.wasSuccessful()) {
+
+ try {
+ rootNode = mapper.readTree(jsonResult);
+ } catch (IOException exc) {
+ LOG.error(AaiUiMsgs.JSON_PROCESSING_ERROR, exc.getMessage());
+ return;
+ }
+
+ JsonNode resultData = rootNode.get("result-data");
+ ArrayNode resultDataArrayNode = null;
+
+ if (resultData != null && resultData.isArray()) {
+ resultDataArrayNode = (ArrayNode) resultData;
+ entityCounters.put(entityType, new AtomicInteger(resultDataArrayNode.size()));
+ }
+ }
+
+ }
+
+ /**
+ * Insert entity type counters.
+ */
+ private void insertEntityTypeCounters() {
+
+ if (esWorkOnHand.get() <= 0) {
+ return;
+ }
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(INSERTION_DATE_TIME_FORMAT);
+ Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+ String currentFormattedTimeStamp = dateFormat.format(timestamp);
+
+ Set> entityCounterEntries = entityCounters.entrySet();
+
+ for (Entry entityCounterEntry : entityCounterEntries) {
+
+ supplyAsync(new Supplier() {
+
+ @Override
+ public Void get() {
+ MDC.setContextMap(contextMap);
+ String jsonString =
+ Json.createObjectBuilder().add("count", entityCounterEntry.getValue().get())
+ .add("entityType", entityCounterEntry.getKey())
+ .add("timestamp", currentFormattedTimeStamp).build().toString();
+
+ String link = null;
+ try {
+ link = getElasticFullUrl("", indexName);
+ OperationResult or =
+ elasticSearchAdapter.doPost(link, jsonString, MediaType.APPLICATION_JSON_TYPE);
+ updateElasticSearchCounters(HttpMethod.POST, entityCounterEntry.getKey(), or);
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_STORE_FAILURE, exc.getMessage());
+ }
+
+ return null;
+ }
+
+ }, esExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ });
+
+ }
+
+ while (esWorkOnHand.get() > 0) {
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException exc) {
+ LOG.error(AaiUiMsgs.INTERRUPTED, "historical Entities", exc.getMessage());
+ }
+ }
+
+ }
+
+ @Override
+ public SynchronizerState getState() {
+
+ if (!isSyncDone()) {
+ return SynchronizerState.PERFORMING_SYNCHRONIZATION;
+ }
+
+ return SynchronizerState.IDLE;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#getStatReport(boolean)
+ */
+ @Override
+ public String getStatReport(boolean showFinalReport) {
+ syncDurationInMs = System.currentTimeMillis() - syncStartedTimeStampInMs;
+ return this.getStatReport(syncDurationInMs, showFinalReport);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ this.shutdownExecutors();
+ }
+
+ @Override
+ protected boolean isSyncDone() {
+
+ int totalWorkOnHand = aaiWorkOnHand.get() + esWorkOnHand.get();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC, indexName + ", isSyncDone(), totalWorkOnHand = "
+ + totalWorkOnHand + " all work enumerated = " + allWorkEnumerated);
+ }
+
+ if (totalWorkOnHand > 0 || !allWorkEnumerated) {
+ return false;
+ }
+
+ this.syncInProgress = false;
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.AbstractEntitySynchronizer#clearCache()
+ */
+ @Override
+ public void clearCache() {
+
+ if (syncInProgress) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
+ "Historical Entity Summarizer in progress, request to clear cache ignored");
+ return;
+ }
+
+ super.clearCache();
+ this.resetCounters();
+ if (entityCounters != null) {
+ entityCounters.clear();
+ }
+
+ allWorkEnumerated = false;
+
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySyncController.java b/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySyncController.java
new file mode 100644
index 0000000..1f7db2e
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/aggregation/sync/HistoricalEntitySyncController.java
@@ -0,0 +1,90 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.aggregation.sync;
+
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.sync.ElasticSearchSchemaFactory;
+import org.onap.aai.sparky.sync.IndexIntegrityValidator;
+import org.onap.aai.sparky.sync.SyncControllerImpl;
+import org.onap.aai.sparky.sync.SyncControllerRegistrar;
+import org.onap.aai.sparky.sync.SyncControllerRegistry;
+import org.onap.aai.sparky.sync.config.ElasticSearchEndpointConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.config.SyncControllerConfig;
+
+public class HistoricalEntitySyncController extends SyncControllerImpl
+ implements SyncControllerRegistrar {
+
+ private SyncControllerRegistry syncControllerRegistry;
+
+ public HistoricalEntitySyncController(SyncControllerConfig syncControllerConfig,
+ ActiveInventoryAdapter aaiAdapter, ElasticSearchAdapter esAdapter,
+ ElasticSearchSchemaConfig schemaConfig, ElasticSearchEndpointConfig endpointConfig,
+ int syncFrequencyInMinutes, NetworkStatisticsConfig aaiStatConfig,
+ NetworkStatisticsConfig esStatConfig) throws Exception {
+ super(syncControllerConfig);
+
+ // final String controllerName = "Historical Entity Count Synchronizer";
+
+ long taskFrequencyInMs = syncFrequencyInMinutes * 60 * 1000;
+
+ setDelayInMs(taskFrequencyInMs);
+ setSyncFrequencyInMs(taskFrequencyInMs);
+
+ IndexIntegrityValidator entityCounterHistoryValidator = new IndexIntegrityValidator(esAdapter,
+ schemaConfig, endpointConfig, ElasticSearchSchemaFactory.getIndexSchema(schemaConfig));
+
+ registerIndexValidator(entityCounterHistoryValidator);
+
+ HistoricalEntitySummarizer historicalSummarizer = new HistoricalEntitySummarizer(schemaConfig,
+ syncControllerConfig.getNumInternalSyncWorkers(),
+ syncControllerConfig.getNumSyncActiveInventoryWorkers(),
+ syncControllerConfig.getNumSyncElasticWorkers(), aaiStatConfig, esStatConfig);
+
+ historicalSummarizer.setAaiAdapter(aaiAdapter);
+ historicalSummarizer.setElasticSearchAdapter(esAdapter);
+
+ registerEntitySynchronizer(historicalSummarizer);
+
+ }
+
+ public SyncControllerRegistry getSyncControllerRegistry() {
+ return syncControllerRegistry;
+ }
+
+ public void setSyncControllerRegistry(SyncControllerRegistry syncControllerRegistry) {
+ this.syncControllerRegistry = syncControllerRegistry;
+ }
+
+ @Override
+ public void registerController() {
+ if (syncControllerRegistry != null) {
+ if (syncControllerConfig.isEnabled()) {
+ syncControllerRegistry.registerSyncController(this);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/analytics/AbstractStatistics.java b/src/main/java/org/onap/aai/sparky/analytics/AbstractStatistics.java
index 9d2fec6..6e7d854 100644
--- a/src/main/java/org/onap/aai/sparky/analytics/AbstractStatistics.java
+++ b/src/main/java/org/onap/aai/sparky/analytics/AbstractStatistics.java
@@ -20,6 +20,7 @@
*
* ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
+
package org.onap.aai.sparky.analytics;
import java.util.HashMap;
@@ -31,35 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger;
public class AbstractStatistics implements ComponentStatistics {
private HashMap namedCounters;
-
- /**
- * @return the namedCounters
- */
- public HashMap getNamedCounters() {
- return namedCounters;
- }
-
- /**
- * @param namedCounters the namedCounters to set
- */
- public void setNamedCounters(HashMap namedCounters) {
- this.namedCounters = namedCounters;
- }
-
- /**
- * @return the namedHistograms
- */
- public HashMap getNamedHistograms() {
- return namedHistograms;
- }
-
- /**
- * @param namedHistograms the namedHistograms to set
- */
- public void setNamedHistograms(HashMap namedHistograms) {
- this.namedHistograms = namedHistograms;
- }
-
private HashMap namedHistograms;
/**
@@ -73,7 +45,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#addCounter(java.lang.String)
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#addCounter(java.lang.String)
*/
/*
* sync-lock the creation of counters during initialization, but run time should not use lock
@@ -96,7 +68,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#pegCounter(java.lang.String)
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#pegCounter(java.lang.String)
*/
@Override
public void pegCounter(String key) {
@@ -112,7 +84,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#incrementCounter(java.lang.String, int)
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#incrementCounter(java.lang.String, int)
*/
@Override
public void incrementCounter(String key, int value) {
@@ -129,7 +101,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#addHistogram(java.lang.String,
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#addHistogram(java.lang.String,
* java.lang.String, long, int, int)
*/
@Override
@@ -147,7 +119,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#updateHistogram(java.lang.String, long)
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#updateHistogram(java.lang.String, long)
*/
@Override
public void updateHistogram(String key, long value) {
@@ -161,7 +133,7 @@ public class AbstractStatistics implements ComponentStatistics {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.analytics.ComponentStatistics#reset()
+ * @see org.openecomp.sparky.analytics.ComponentStatistics#reset()
*/
@Override
public void reset() {
diff --git a/src/main/java/org/onap/aai/sparky/analytics/HistoricalCounter.java b/src/main/java/org/onap/aai/sparky/analytics/HistoricalCounter.java
index 622693c..50941cc 100644
--- a/src/main/java/org/onap/aai/sparky/analytics/HistoricalCounter.java
+++ b/src/main/java/org/onap/aai/sparky/analytics/HistoricalCounter.java
@@ -20,7 +20,6 @@
*
* ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
-
package org.onap.aai.sparky.analytics;
/**
@@ -33,62 +32,6 @@ public class HistoricalCounter {
private double min;
- /**
- * @return the totalOfSamples
- */
- public double getTotalOfSamples() {
- return totalOfSamples;
- }
-
- /**
- * @param totalOfSamples the totalOfSamples to set
- */
- public void setTotalOfSamples(double totalOfSamples) {
- this.totalOfSamples = totalOfSamples;
- }
-
- /**
- * @return the maintainSingleValue
- */
- public boolean isMaintainSingleValue() {
- return maintainSingleValue;
- }
-
- /**
- * @param maintainSingleValue the maintainSingleValue to set
- */
- public void setMaintainSingleValue(boolean maintainSingleValue) {
- this.maintainSingleValue = maintainSingleValue;
- }
-
- /**
- * @param min the min to set
- */
- public void setMin(double min) {
- this.min = min;
- }
-
- /**
- * @param max the max to set
- */
- public void setMax(double max) {
- this.max = max;
- }
-
- /**
- * @param numSamples the numSamples to set
- */
- public void setNumSamples(long numSamples) {
- this.numSamples = numSamples;
- }
-
- /**
- * @param value the value to set
- */
- public void setValue(double value) {
- this.value = value;
- }
-
private double max;
private double totalOfSamples;
@@ -175,6 +118,31 @@ public class HistoricalCounter {
return (totalOfSamples / numSamples);
}
+ public void setMin(double min) {
+ this.min = min;
+ }
+
+ public void setMax(double max) {
+ this.max = max;
+ }
+
+ public double getTotalOfSamples() {
+ return totalOfSamples;
+ }
+
+ public void setTotalOfSamples(double totalOfSamples) {
+ this.totalOfSamples = totalOfSamples;
+ }
+
+ public void setNumSamples(long numSamples) {
+ this.numSamples = numSamples;
+ }
+
+ public void setMaintainSingleValue(boolean maintainSingleValue) {
+ this.maintainSingleValue = maintainSingleValue;
+ }
+
+
/**
* Reset.
*/
diff --git a/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutoSuggestionSyncController.java b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutoSuggestionSyncController.java
new file mode 100644
index 0000000..950eb45
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutoSuggestionSyncController.java
@@ -0,0 +1,97 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.autosuggestion.sync;
+
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.sync.ElasticSearchIndexCleaner;
+import org.onap.aai.sparky.sync.ElasticSearchSchemaFactory;
+import org.onap.aai.sparky.sync.IndexCleaner;
+import org.onap.aai.sparky.sync.IndexIntegrityValidator;
+import org.onap.aai.sparky.sync.SyncControllerImpl;
+import org.onap.aai.sparky.sync.SyncControllerRegistrar;
+import org.onap.aai.sparky.sync.SyncControllerRegistry;
+import org.onap.aai.sparky.sync.config.ElasticSearchEndpointConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.config.SyncControllerConfig;
+
+public class AutoSuggestionSyncController extends SyncControllerImpl
+ implements SyncControllerRegistrar {
+
+ private SyncControllerRegistry syncControllerRegistry;
+
+ public AutoSuggestionSyncController(SyncControllerConfig syncControllerConfig,
+ ActiveInventoryAdapter aaiAdapter, ElasticSearchAdapter esAdapter,
+ ElasticSearchSchemaConfig schemaConfig, ElasticSearchEndpointConfig endpointConfig,
+ NetworkStatisticsConfig aaiStatConfig, NetworkStatisticsConfig esStatConfig)
+ throws Exception {
+ super(syncControllerConfig);
+
+ // final String controllerName = "Auto Suggestion Synchronizer";
+
+ IndexIntegrityValidator autoSuggestionIndexValidator = new IndexIntegrityValidator(esAdapter,
+ schemaConfig, endpointConfig, ElasticSearchSchemaFactory.getIndexSchema(schemaConfig));
+
+ registerIndexValidator(autoSuggestionIndexValidator);
+
+ AutosuggestionSynchronizer suggestionSynchronizer = new AutosuggestionSynchronizer(schemaConfig,
+ syncControllerConfig.getNumInternalSyncWorkers(),
+ syncControllerConfig.getNumSyncActiveInventoryWorkers(),
+ syncControllerConfig.getNumSyncElasticWorkers(), aaiStatConfig, esStatConfig);
+
+ suggestionSynchronizer.setAaiAdapter(aaiAdapter);
+ suggestionSynchronizer.setElasticSearchAdapter(esAdapter);
+
+ registerEntitySynchronizer(suggestionSynchronizer);
+
+ IndexCleaner autosuggestIndexCleaner =
+ new ElasticSearchIndexCleaner(esAdapter, endpointConfig, schemaConfig);
+
+ registerIndexCleaner(autosuggestIndexCleaner);
+
+ }
+
+ public SyncControllerRegistry getSyncControllerRegistry() {
+ return syncControllerRegistry;
+ }
+
+
+
+ public void setSyncControllerRegistry(SyncControllerRegistry syncControllerRegistry) {
+ this.syncControllerRegistry = syncControllerRegistry;
+ }
+
+
+
+ @Override
+ public void registerController() {
+
+ if (syncControllerRegistry != null) {
+ if (syncControllerConfig.isEnabled()) {
+ syncControllerRegistry.registerSyncController(this);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizer.java b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizer.java
new file mode 100644
index 0000000..4ce7ce3
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/AutosuggestionSynchronizer.java
@@ -0,0 +1,749 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.autosuggestion.sync;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+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.OxmEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
+import org.onap.aai.sparky.config.oxm.SuggestionEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.SuggestionEntityLookup;
+import org.onap.aai.sparky.dal.NetworkTransaction;
+import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
+import org.onap.aai.sparky.dal.rest.HttpMethod;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.AbstractEntitySynchronizer;
+import org.onap.aai.sparky.sync.IndexSynchronizer;
+import org.onap.aai.sparky.sync.SynchronizerConstants;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.entity.SelfLinkDescriptor;
+import org.onap.aai.sparky.sync.entity.SuggestionSearchEntity;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.sync.enumeration.SynchronizerState;
+import org.onap.aai.sparky.sync.task.PerformActiveInventoryRetrieval;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchPut;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchRetrieval;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.onap.aai.sparky.util.SuggestionsPermutation;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * The Class AutosuggestionSynchronizer.
+ */
+public class AutosuggestionSynchronizer extends AbstractEntitySynchronizer
+ implements IndexSynchronizer {
+
+ private class RetrySuggestionEntitySyncContainer {
+ NetworkTransaction txn;
+ SuggestionSearchEntity ssec;
+
+ /**
+ * Instantiates a new RetrySuggestionEntitySyncContainer.
+ *
+ * @param txn the txn
+ * @param icer the icer
+ */
+ public RetrySuggestionEntitySyncContainer(NetworkTransaction txn, SuggestionSearchEntity icer) {
+ this.txn = txn;
+ this.ssec = icer;
+ }
+
+ public NetworkTransaction getNetworkTransaction() {
+ return txn;
+ }
+
+ public SuggestionSearchEntity getSuggestionSearchEntity() {
+ return ssec;
+ }
+ }
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(AutosuggestionSynchronizer.class);
+ private static final String INSERTION_DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmssZ";
+
+ private boolean allWorkEnumerated;
+ private Deque selflinks;
+ private ConcurrentHashMap entityCounters;
+ private boolean syncInProgress;
+ private Map contextMap;
+ protected ExecutorService esPutExecutor;
+ private Deque retryQueue;
+ private Map retryLimitTracker;
+
+ /**
+ * Instantiates a new historical entity summarizer.
+ *
+ * @param indexName the index name
+ * @throws Exception the exception
+ */
+ public AutosuggestionSynchronizer(ElasticSearchSchemaConfig schemaConfig, int internalSyncWorkers,
+ int aaiWorkers, int esWorkers, NetworkStatisticsConfig aaiStatConfig,
+ NetworkStatisticsConfig esStatConfig) throws Exception {
+ super(LOG, "ASES-" + schemaConfig.getIndexName().toUpperCase(), internalSyncWorkers, aaiWorkers,
+ esWorkers, schemaConfig.getIndexName(), aaiStatConfig, esStatConfig);
+
+ this.allWorkEnumerated = false;
+ this.selflinks = new ConcurrentLinkedDeque();
+ this.entityCounters = new ConcurrentHashMap();
+ this.synchronizerName = "Autosuggestion Entity Synchronizer";
+ this.enabledStatFlags = EnumSet.of(StatFlag.AAI_REST_STATS, StatFlag.ES_REST_STATS);
+ this.syncInProgress = false;
+ this.contextMap = MDC.getCopyOfContextMap();
+ this.esPutExecutor = NodeUtils.createNamedExecutor("SUES-ES-PUT", 5, LOG);
+ this.syncDurationInMs = -1;
+ }
+
+ /**
+ * Collect all the work.
+ *
+ * @return the operation state
+ */
+ private OperationState collectAllTheWork() {
+ final Map contextMap = MDC.getCopyOfContextMap();
+ Map descriptorMap =
+ SuggestionEntityLookup.getInstance().getSuggestionSearchEntityDescriptors();
+
+ if (descriptorMap.isEmpty()) {
+ LOG.error(AaiUiMsgs.ERROR_LOADING_OXM_SUGGESTIBLE_ENTITIES);
+ LOG.info(AaiUiMsgs.ERROR_LOADING_OXM_SUGGESTIBLE_ENTITIES);
+ return OperationState.ERROR;
+ }
+
+ Collection syncTypes = descriptorMap.keySet();
+
+ try {
+
+ /*
+ * launch a parallel async thread to process the documents for each entity-type (to max the of
+ * the configured executor anyway)
+ */
+
+ aaiWorkOnHand.set(syncTypes.size());
+
+ for (String key : syncTypes) {
+
+ supplyAsync(new Supplier() {
+
+ @Override
+ public Void get() {
+ MDC.setContextMap(contextMap);
+ OperationResult typeLinksResult = null;
+ try {
+ typeLinksResult = aaiAdapter.getSelfLinksByEntityType(key);
+ aaiWorkOnHand.decrementAndGet();
+ processEntityTypeSelfLinks(typeLinksResult);
+ } catch (Exception exc) {
+ // TODO -> LOG, what should be logged here?
+ }
+
+ return null;
+ }
+
+ }, aaiExecutor).whenComplete((result, error) -> {
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ERROR_GENERIC,
+ "An error occurred getting data from AAI. Error = " + error.getMessage());
+ }
+ });
+
+ }
+
+ while (aaiWorkOnHand.get() != 0) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.WAIT_FOR_ALL_SELFLINKS_TO_BE_COLLECTED);
+ }
+
+ Thread.sleep(1000);
+ }
+
+ aaiWorkOnHand.set(selflinks.size());
+ allWorkEnumerated = true;
+ syncEntityTypes();
+
+ while (!isSyncDone()) {
+ performRetrySync();
+ Thread.sleep(1000);
+ }
+
+ /*
+ * Make sure we don't hang on to retries that failed which could cause issues during future
+ * syncs
+ */
+ retryLimitTracker.clear();
+
+ } catch (Exception exc) {
+ // TODO -> LOG, waht should be logged here?
+ }
+
+ return OperationState.OK;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#doSync()
+ */
+ @Override
+ public OperationState doSync() {
+ this.syncDurationInMs = -1;
+ syncStartedTimeStampInMs = System.currentTimeMillis();
+ String txnID = NodeUtils.getRandomTxnId();
+ MdcContext.initialize(txnID, "AutosuggestionSynchronizer", "", "Sync", "");
+
+ return collectAllTheWork();
+ }
+
+ /**
+ * Process entity type self links.
+ *
+ * @param operationResult the operation result
+ */
+ private void processEntityTypeSelfLinks(OperationResult operationResult) {
+
+ JsonNode rootNode = null;
+
+ final String jsonResult = operationResult.getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0 && operationResult.wasSuccessful()) {
+
+ try {
+ rootNode = mapper.readTree(jsonResult);
+ } catch (IOException exc) {
+ String message = "Could not deserialize JSON (representing operation result) as node tree. "
+ + "Operation result = " + jsonResult + ". " + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.JSON_PROCESSING_ERROR, message);
+ }
+
+ JsonNode resultData = rootNode.get("result-data");
+ ArrayNode resultDataArrayNode = null;
+
+ if (resultData.isArray()) {
+ resultDataArrayNode = (ArrayNode) resultData;
+
+ Iterator elementIterator = resultDataArrayNode.elements();
+ JsonNode element = null;
+
+ while (elementIterator.hasNext()) {
+ element = elementIterator.next();
+
+ final String resourceType = NodeUtils.getNodeFieldAsText(element, "resource-type");
+ final String resourceLink = NodeUtils.getNodeFieldAsText(element, "resource-link");
+
+ OxmEntityDescriptor descriptor = null;
+
+ if (resourceType != null && resourceLink != null) {
+
+ descriptor = OxmEntityLookup.getInstance().getEntityDescriptors().get(resourceType);
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, resourceType);
+ // go to next element in iterator
+ continue;
+ }
+ selflinks.add(new SelfLinkDescriptor(resourceLink,
+ SynchronizerConstants.NODES_ONLY_MODIFIER, resourceType));
+
+
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sync entity types.
+ */
+ private void syncEntityTypes() {
+
+ while (selflinks.peek() != null) {
+
+ SelfLinkDescriptor linkDescriptor = selflinks.poll();
+ aaiWorkOnHand.decrementAndGet();
+
+ OxmEntityDescriptor descriptor = null;
+
+ if (linkDescriptor.getSelfLink() != null && linkDescriptor.getEntityType() != null) {
+
+ descriptor = OxmEntityLookup.getInstance().getEntityDescriptors()
+ .get(linkDescriptor.getEntityType());
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, linkDescriptor.getEntityType());
+ // go to next element in iterator
+ continue;
+ }
+
+ NetworkTransaction txn = new NetworkTransaction();
+ txn.setDescriptor(descriptor);
+ txn.setLink(linkDescriptor.getSelfLink());
+ txn.setOperationType(HttpMethod.GET);
+ txn.setEntityType(linkDescriptor.getEntityType());
+
+ aaiWorkOnHand.incrementAndGet();
+
+ supplyAsync(new PerformActiveInventoryRetrieval(txn, aaiAdapter), aaiExecutor)
+ .whenComplete((result, error) -> {
+
+ aaiWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.AAI_RETRIEVAL_FAILED_GENERIC, error.getLocalizedMessage());
+ } else {
+ if (result == null) {
+ LOG.error(AaiUiMsgs.AAI_RETRIEVAL_FAILED_FOR_SELF_LINK,
+ linkDescriptor.getSelfLink());
+ } else {
+ updateActiveInventoryCounters(result);
+ fetchDocumentForUpsert(result);
+ }
+ }
+ });
+ }
+
+ }
+
+ }
+
+ /*
+ * 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 getSuggestableAttrNamesFromReponse(JsonNode node, String entityName) {
+ List suggestableAttr = new ArrayList();
+ HashMap desc =
+ SuggestionEntityLookup.getInstance().getSuggestionSearchEntityOxmModel().get(entityName);
+ String attr = desc.get("suggestibleAttributes");
+ suggestableAttr = Arrays.asList(attr.split(","));
+ List suggestableValue = new ArrayList<>();
+ for (String attribute : suggestableAttr) {
+ if (node.get(attribute) != null && node.get(attribute).asText().length() > 0) {
+ suggestableValue.add(attribute);
+ }
+ }
+ return suggestableValue;
+ }
+
+ /**
+ * Fetch all the documents for upsert. Based on the number of permutations that are available the
+ * number of documents will be different
+ *
+ * @param txn the txn
+ */
+ private void fetchDocumentForUpsert(NetworkTransaction txn) {
+ if (!txn.getOperationResult().wasSuccessful()) {
+ String message = "Self link failure. Result - " + txn.getOperationResult().getResult();
+ LOG.error(AaiUiMsgs.ERROR_GENERIC, message);
+ return;
+ }
+ try {
+ final String jsonResult = txn.getOperationResult().getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0) {
+
+ // Step 1: Calculate the number of possible permutations of attributes
+ String entityName = txn.getDescriptor().getEntityName();
+ JsonNode entityNode = mapper.readTree(jsonResult);
+
+ List availableSuggestableAttrName =
+ getSuggestableAttrNamesFromReponse(entityNode, entityName);
+
+ ArrayList> uniqueLists =
+ SuggestionsPermutation.getNonEmptyUniqueLists(availableSuggestableAttrName);
+ // Now we have a list of all possible permutations for the status that are
+ // defined for this entity type. Try inserting a document for every combination.
+ for (ArrayList uniqueList : uniqueLists) {
+
+ SuggestionSearchEntity sse =
+ new SuggestionSearchEntity(SuggestionEntityLookup.getInstance());
+ sse.setSuggestableAttr(uniqueList);
+ sse.setFilterBasedPayloadFromResponse(entityNode, entityName, uniqueList);
+ sse.setLink(ActiveInventoryConfig.extractResourcePath(txn.getLink()));
+ populateSuggestionSearchEntityDocument(sse, jsonResult, txn);
+ // The unique id for the document will be created at derive fields
+ sse.deriveFields();
+ // Insert the document only if it has valid statuses
+ if (sse.isSuggestableDoc()) {
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + sse.getId(), getIndexName());
+ } 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, sse);
+ }
+ });
+ }
+ }
+ }
+ }
+ } catch (JsonProcessingException exc) {
+ // TODO -> LOG, waht should be logged here?
+ } catch (IOException exc) {
+ // TODO -> LOG, waht should be logged here?
+ }
+ }
+
+ protected void populateSuggestionSearchEntityDocument(SuggestionSearchEntity sse, String result,
+ NetworkTransaction txn) throws JsonProcessingException, IOException {
+
+ OxmEntityDescriptor resultDescriptor = txn.getDescriptor();
+
+ sse.setEntityType(resultDescriptor.getEntityName());
+
+ JsonNode entityNode = mapper.readTree(result);
+
+ List primaryKeyValues = new ArrayList();
+ String pkeyValue = null;
+
+ for (String keyName : resultDescriptor.getPrimaryKeyAttributeNames()) {
+ pkeyValue = NodeUtils.getNodeFieldAsText(entityNode, keyName);
+ if (pkeyValue != null) {
+ primaryKeyValues.add(pkeyValue);
+ } else {
+ String message = "populateSuggestionSearchEntityDocument(),"
+ + " pKeyValue is null for entityType = " + resultDescriptor.getEntityName();
+ LOG.warn(AaiUiMsgs.WARN_GENERIC, message);
+ }
+ }
+
+ final String primaryCompositeKeyValue = NodeUtils.concatArray(primaryKeyValues, "/");
+ sse.setEntityPrimaryKeyValue(primaryCompositeKeyValue);
+ sse.generateSuggestionInputPermutations();
+ }
+
+ protected void performDocumentUpsert(NetworkTransaction esGetTxn, SuggestionSearchEntity sse) {
+ /**
+ *
+ *
+ * As part of the response processing we need to do the following:
+ * - 1. Extract the version (if present), it will be the ETAG when we use the
+ * Search-Abstraction-Service
+ *
- 2. Spawn next task which is to do the PUT operation into elastic with or with the version
+ * tag
+ *
- a) if version is null or RC=404, then standard put, no _update with version tag
+ *
- b) if version != null, do PUT with _update?version= versionNumber in the URI to elastic
+ *
+ *
+ */
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + sse.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_LINK_UPSERT, exc.getLocalizedMessage());
+ return;
+ }
+
+ boolean wasEntryDiscovered = false;
+ if (esGetTxn.getOperationResult().getResultCode() == 404) {
+ LOG.info(AaiUiMsgs.ES_SIMPLE_PUT, sse.getEntityPrimaryKeyValue());
+ } else if (esGetTxn.getOperationResult().getResultCode() == 200) {
+ wasEntryDiscovered = true;
+ } else {
+ /*
+ * Not being a 200 does not mean a failure. eg 201 is returned for created. and 500 for es not
+ * found TODO -> Should we return.
+ */
+ LOG.error(AaiUiMsgs.ES_OPERATION_RETURN_CODE,
+ String.valueOf(esGetTxn.getOperationResult().getResultCode()));
+ return;
+ }
+ // Insert a new document only if the paylod is different.
+ // This is determined by hashing the payload and using it as a id for the document
+ //
+ if (!wasEntryDiscovered) {
+ try {
+ String jsonPayload = null;
+
+ jsonPayload = sse.getAsJson();
+ if (link != null && jsonPayload != null) {
+
+ NetworkTransaction updateElasticTxn = new NetworkTransaction();
+ updateElasticTxn.setLink(link);
+ updateElasticTxn.setEntityType(esGetTxn.getEntityType());
+ updateElasticTxn.setDescriptor(esGetTxn.getDescriptor());
+ updateElasticTxn.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ supplyAsync(
+ new PerformElasticSearchPut(jsonPayload, updateElasticTxn, elasticSearchAdapter),
+ esPutExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ String message = "Suggestion search entity sync UPDATE PUT error - "
+ + error.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ES_SUGGESTION_SEARCH_ENTITY_SYNC_ERROR, message);
+ } else {
+ updateElasticSearchCounters(result);
+ processStoreDocumentResult(result, esGetTxn, sse);
+ }
+ });
+ }
+ } catch (Exception exc) {
+ String message =
+ "Exception caught during suggestion search entity sync PUT operation. Message - "
+ + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ES_SUGGESTION_SEARCH_ENTITY_SYNC_ERROR, message);
+ }
+ }
+ }
+
+ private void processStoreDocumentResult(NetworkTransaction esPutResult,
+ NetworkTransaction esGetResult, SuggestionSearchEntity sse) {
+
+ OperationResult or = esPutResult.getOperationResult();
+
+ if (!or.wasSuccessful()) {
+ if (or.getResultCode() == VERSION_CONFLICT_EXCEPTION_CODE) {
+
+ if (shouldAllowRetry(sse.getId())) {
+ esWorkOnHand.incrementAndGet();
+
+ RetrySuggestionEntitySyncContainer rssec =
+ new RetrySuggestionEntitySyncContainer(esGetResult, sse);
+ retryQueue.push(rssec);
+
+ String message = "Store document failed during suggestion search entity synchronization"
+ + " due to version conflict. Entity will be re-synced.";
+ LOG.warn(AaiUiMsgs.ES_SUGGESTION_SEARCH_ENTITY_SYNC_ERROR, message);
+ }
+ } else {
+ String message =
+ "Store document failed during suggestion search entity synchronization with result code "
+ + or.getResultCode() + " and result message " + or.getResult();
+ LOG.error(AaiUiMsgs.ES_SUGGESTION_SEARCH_ENTITY_SYNC_ERROR, message);
+ }
+ }
+ }
+
+ /**
+ * Perform retry sync.
+ */
+ private void performRetrySync() {
+ while (retryQueue.peek() != null) {
+
+ RetrySuggestionEntitySyncContainer susc = retryQueue.poll();
+ if (susc != null) {
+
+ SuggestionSearchEntity sus = susc.getSuggestionSearchEntity();
+ NetworkTransaction txn = susc.getNetworkTransaction();
+
+ String link = null;
+ try {
+ /*
+ * In this retry flow the se object has already derived its fields
+ */
+ link = getElasticFullUrl("/" + sus.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_FAILED_TO_CONSTRUCT_URI, exc.getLocalizedMessage());
+ }
+
+ if (link != null) {
+ NetworkTransaction retryTransaction = new NetworkTransaction();
+ retryTransaction.setLink(link);
+ retryTransaction.setEntityType(txn.getEntityType());
+ retryTransaction.setDescriptor(txn.getDescriptor());
+ retryTransaction.setOperationType(HttpMethod.GET);
+
+ /*
+ * IMPORTANT - DO NOT incrementAndGet the esWorkOnHand as this is a retry flow! We already
+ * called incrementAndGet when queuing the failed PUT!
+ */
+
+ supplyAsync(new PerformElasticSearchRetrieval(retryTransaction, elasticSearchAdapter),
+ esExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ES_RETRIEVAL_FAILED_RESYNC, error.getLocalizedMessage());
+ } else {
+ updateElasticSearchCounters(result);
+ performDocumentUpsert(result, sus);
+ }
+ });
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Should allow retry.
+ *
+ * @param id the id
+ * @return true, if successful
+ */
+ private boolean shouldAllowRetry(String id) {
+ boolean isRetryAllowed = true;
+ if (retryLimitTracker.get(id) != null) {
+ Integer currentCount = retryLimitTracker.get(id);
+ if (currentCount.intValue() >= RETRY_COUNT_PER_ENTITY_LIMIT.intValue()) {
+ isRetryAllowed = false;
+ String message = "Searchable entity re-sync limit reached for " + id
+ + ", re-sync will no longer be attempted for this entity";
+ LOG.error(AaiUiMsgs.ES_SEARCHABLE_ENTITY_SYNC_ERROR, message);
+ } else {
+ Integer newCount = new Integer(currentCount.intValue() + 1);
+ retryLimitTracker.put(id, newCount);
+ }
+ } else {
+ Integer firstRetryCount = new Integer(1);
+ retryLimitTracker.put(id, firstRetryCount);
+ }
+
+ return isRetryAllowed;
+ }
+
+
+
+ @Override
+ public SynchronizerState getState() {
+
+ if (!isSyncDone()) {
+ return SynchronizerState.PERFORMING_SYNCHRONIZATION;
+ }
+
+ return SynchronizerState.IDLE;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#getStatReport(boolean)
+ */
+ @Override
+ public String getStatReport(boolean showFinalReport) {
+ syncDurationInMs = System.currentTimeMillis() - syncStartedTimeStampInMs;
+ return getStatReport(syncDurationInMs, showFinalReport);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ this.shutdownExecutors();
+ }
+
+ @Override
+ protected boolean isSyncDone() {
+
+ int totalWorkOnHand = aaiWorkOnHand.get() + esWorkOnHand.get();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC, indexName + ", isSyncDone(), totalWorkOnHand = "
+ + totalWorkOnHand + " all work enumerated = " + allWorkEnumerated);
+ }
+
+ if (totalWorkOnHand > 0 || !allWorkEnumerated) {
+ return false;
+ }
+
+ this.syncInProgress = false;
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.AbstractEntitySynchronizer#clearCache()
+ */
+ @Override
+ public void clearCache() {
+
+ if (syncInProgress) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
+ "Autosuggestion Entity Summarizer in progress, request to clear cache ignored");
+ return;
+ }
+
+ super.clearCache();
+ this.resetCounters();
+ if (entityCounters != null) {
+ entityCounters.clear();
+ }
+
+ allWorkEnumerated = false;
+
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSuggestionSynchronizer.java b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSuggestionSynchronizer.java
new file mode 100644
index 0000000..c6fa69b
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSuggestionSynchronizer.java
@@ -0,0 +1,192 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.autosuggestion.sync;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+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.dal.NetworkTransaction;
+import org.onap.aai.sparky.dal.rest.HttpMethod;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.AbstractEntitySynchronizer;
+import org.onap.aai.sparky.sync.IndexSynchronizer;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.entity.AggregationSuggestionEntity;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.sync.enumeration.SynchronizerState;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchPut;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.slf4j.MDC;
+
+
+public class VnfAliasSuggestionSynchronizer extends AbstractEntitySynchronizer
+ implements IndexSynchronizer {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(VnfAliasSuggestionSynchronizer.class);
+
+ private boolean isSyncInProgress;
+ private boolean shouldPerformRetry;
+ private Map contextMap;
+ protected ExecutorService esPutExecutor;
+
+ public VnfAliasSuggestionSynchronizer(ElasticSearchSchemaConfig schemaConfig,
+ int internalSyncWorkers, int aaiWorkers, int esWorkers, NetworkStatisticsConfig aaiStatConfig,
+ NetworkStatisticsConfig esStatConfig) throws Exception {
+ super(LOG, "VASS-" + schemaConfig.getIndexName().toUpperCase(), internalSyncWorkers, aaiWorkers,
+ esWorkers, schemaConfig.getIndexName(), aaiStatConfig, esStatConfig);
+
+ this.isSyncInProgress = false;
+ this.shouldPerformRetry = false;
+ this.synchronizerName = "VNFs Alias Suggestion Synchronizer";
+ this.contextMap = MDC.getCopyOfContextMap();
+ this.esPutExecutor = NodeUtils.createNamedExecutor("ASS-ES-PUT", 2, LOG);
+ }
+
+ @Override
+ protected boolean isSyncDone() {
+ int totalWorkOnHand = esWorkOnHand.get();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.DEBUG_GENERIC,
+ indexName + ", isSyncDone(), totalWorkOnHand = " + totalWorkOnHand);
+ }
+
+ if (totalWorkOnHand > 0 || !isSyncInProgress) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public OperationState doSync() {
+ isSyncInProgress = true;
+ this.syncDurationInMs = -1;
+ syncStartedTimeStampInMs = System.currentTimeMillis();
+
+ syncEntity();
+
+ while (!isSyncDone()) {
+ try {
+ if (shouldPerformRetry) {
+ syncEntity();
+ }
+ Thread.sleep(1000);
+ } catch (Exception exc) {
+ // We don't care about this exception
+ }
+ }
+
+ return OperationState.OK;
+ }
+
+ private void syncEntity() {
+ String txnId = NodeUtils.getRandomTxnId();
+ MdcContext.initialize(txnId, synchronizerName, "", "Sync", "");
+
+ AggregationSuggestionEntity syncEntity = new AggregationSuggestionEntity();
+ syncEntity.deriveFields();
+ syncEntity.initializeFilters();
+
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + syncEntity.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_LINK_UPSERT, exc.getLocalizedMessage());
+ }
+
+ try {
+ String jsonPayload = null;
+ jsonPayload = syncEntity.getAsJson();
+ if (link != null && jsonPayload != null) {
+
+ NetworkTransaction elasticPutTxn = new NetworkTransaction();
+ elasticPutTxn.setLink(link);
+ elasticPutTxn.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ final Map contextMap = MDC.getCopyOfContextMap();
+ supplyAsync(new PerformElasticSearchPut(jsonPayload, elasticPutTxn, elasticSearchAdapter,
+ contextMap), esPutExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ String message = "Aggregation suggestion entity sync UPDATE PUT error - "
+ + error.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ES_AGGREGATION_SUGGESTION_ENTITY_SYNC_ERROR, message);
+ } else {
+ updateElasticSearchCounters(result);
+ wasEsOperationSuccessful(result);
+ }
+ });
+ }
+ } catch (Exception exc) {
+ String message =
+ "Exception caught during aggregation suggestion entity sync PUT operation. Message - "
+ + exc.getLocalizedMessage();
+ LOG.error(AaiUiMsgs.ES_AGGREGATION_SUGGESTION_ENTITY_SYNC_ERROR, message);
+ }
+ }
+
+ private void wasEsOperationSuccessful(NetworkTransaction result) {
+ if (result != null) {
+ OperationResult opResult = result.getOperationResult();
+
+ if (!opResult.wasSuccessful()) {
+ shouldPerformRetry = true;
+ } else {
+ isSyncInProgress = false;
+ shouldPerformRetry = false;
+ }
+ }
+ }
+
+ @Override
+ public SynchronizerState getState() {
+ if (!isSyncDone()) {
+ return SynchronizerState.PERFORMING_SYNCHRONIZATION;
+ }
+
+ return SynchronizerState.IDLE;
+ }
+
+ @Override
+ public String getStatReport(boolean shouldDisplayFinalReport) {
+ syncDurationInMs = System.currentTimeMillis() - syncStartedTimeStampInMs;
+ return getStatReport(syncDurationInMs, shouldDisplayFinalReport);
+ }
+
+ @Override
+ public void shutdown() {
+ this.shutdownExecutors();
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSyncController.java b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSyncController.java
new file mode 100644
index 0000000..3376eed
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/autosuggestion/sync/VnfAliasSyncController.java
@@ -0,0 +1,95 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.autosuggestion.sync;
+
+import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.sync.ElasticSearchIndexCleaner;
+import org.onap.aai.sparky.sync.ElasticSearchSchemaFactory;
+import org.onap.aai.sparky.sync.IndexCleaner;
+import org.onap.aai.sparky.sync.IndexIntegrityValidator;
+import org.onap.aai.sparky.sync.SyncControllerImpl;
+import org.onap.aai.sparky.sync.SyncControllerRegistrar;
+import org.onap.aai.sparky.sync.SyncControllerRegistry;
+import org.onap.aai.sparky.sync.config.ElasticSearchEndpointConfig;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.config.SyncControllerConfig;
+
+public class VnfAliasSyncController extends SyncControllerImpl implements SyncControllerRegistrar {
+
+ private SyncControllerRegistry syncControllerRegistry;
+
+ public VnfAliasSyncController(SyncControllerConfig syncControllerConfig,
+ ActiveInventoryAdapter aaiAdapter, ElasticSearchAdapter esAdapter,
+ ElasticSearchSchemaConfig schemaConfig, ElasticSearchEndpointConfig endpointConfig,
+ NetworkStatisticsConfig aaiStatConfig, NetworkStatisticsConfig esStatConfig)
+ throws Exception {
+ super(syncControllerConfig);
+
+ // final String controllerName = "VNFs Alias Suggestion Synchronizer";
+
+ IndexIntegrityValidator indexValidator = new IndexIntegrityValidator(esAdapter, schemaConfig,
+ endpointConfig, ElasticSearchSchemaFactory.getIndexSchema(schemaConfig));
+
+ registerIndexValidator(indexValidator);
+
+ VnfAliasSuggestionSynchronizer synchronizer = new VnfAliasSuggestionSynchronizer(schemaConfig,
+ syncControllerConfig.getNumInternalSyncWorkers(),
+ syncControllerConfig.getNumSyncActiveInventoryWorkers(),
+ syncControllerConfig.getNumSyncElasticWorkers(), aaiStatConfig, esStatConfig);
+
+ synchronizer.setAaiAdapter(aaiAdapter);
+ synchronizer.setElasticSearchAdapter(esAdapter);
+
+ registerEntitySynchronizer(synchronizer);
+
+
+ IndexCleaner indexCleaner =
+ new ElasticSearchIndexCleaner(esAdapter, endpointConfig, schemaConfig);
+
+ registerIndexCleaner(indexCleaner);
+
+ }
+
+ public SyncControllerRegistry getSyncControllerRegistry() {
+ return syncControllerRegistry;
+ }
+
+ public void setSyncControllerRegistry(SyncControllerRegistry syncControllerRegistry) {
+ this.syncControllerRegistry = syncControllerRegistry;
+ }
+
+ @Override
+ public void registerController() {
+
+ if (syncControllerRegistry != null) {
+ if (syncControllerConfig.isEnabled()) {
+ syncControllerRegistry.registerSyncController(this);
+ }
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/common/search/CommonSearchSuggestion.java b/src/main/java/org/onap/aai/sparky/common/search/CommonSearchSuggestion.java
new file mode 100644
index 0000000..8a3f119
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/common/search/CommonSearchSuggestion.java
@@ -0,0 +1,88 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.common.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aai.sparky.search.entity.SearchSuggestion;
+import org.onap.aai.sparky.search.filters.entity.UiFilterValueEntity;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+@JsonInclude(Include.NON_NULL)
+public class CommonSearchSuggestion implements SearchSuggestion {
+ protected String hashId;
+ protected String route;
+ protected String text;
+ protected List filterValues = new ArrayList<>();
+
+ public CommonSearchSuggestion() {}
+
+ public CommonSearchSuggestion(String hashId, String route, String text, String perspective,
+ List filterValues) {
+ this.hashId = hashId;
+ this.route = route;
+ this.text = text;
+ this.filterValues = filterValues;
+ }
+
+ public List getFilterValues() {
+ return filterValues;
+ }
+
+ public String getHashId() {
+ return hashId;
+ }
+
+ public String getRoute() {
+ return route;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setHashId(String hashId) {
+ this.hashId = hashId;
+ }
+
+ public void setRoute(String route) {
+ this.route = route;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return "CommonSearchSuggestion [" + (hashId != null ? "hashId=" + hashId + ", " : "")
+ + (route != null ? "route=" + route + ", " : "")
+ + (text != null ? "text=" + text + ", " : "")
+ + (filterValues != null ? "filterValues=" + filterValues : "") + "]";
+ }
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/Configurable.java b/src/main/java/org/onap/aai/sparky/config/Configurable.java
deleted file mode 100644
index d108bef..0000000
--- a/src/main/java/org/onap/aai/sparky/config/Configurable.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-package org.onap.aai.sparky.config;
-
-import org.onap.aai.sparky.config.exception.ConfigurationException;
-
-/**
- * The Interface Configurable.
- */
-public interface Configurable {
-
- public boolean isValid();
-
- public boolean isInitialized();
-
- /**
- * Load config.
- *
- * @throws ConfigurationException the configuration exception
- */
- public void loadConfig() throws ConfigurationException;
-
-}
diff --git a/src/main/java/org/onap/aai/sparky/config/exception/ConfigurationException.java b/src/main/java/org/onap/aai/sparky/config/exception/ConfigurationException.java
deleted file mode 100644
index f796c38..0000000
--- a/src/main/java/org/onap/aai/sparky/config/exception/ConfigurationException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-package org.onap.aai.sparky.config.exception;
-
-
-/**
- * The Class ConfigurationException.
- */
-public class ConfigurationException extends Exception {
-
-}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReference.java b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReference.java
index e4a9f90..1df9296 100644
--- a/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReference.java
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReference.java
@@ -20,7 +20,6 @@
*
* ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
-
package org.onap.aai.sparky.config.oxm;
import java.util.ArrayList;
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceDescriptor.java
new file mode 100644
index 0000000..f0e6d4e
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceDescriptor.java
@@ -0,0 +1,65 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+public class CrossEntityReferenceDescriptor extends OxmEntityDescriptor {
+ protected CrossEntityReference crossEntityReference;
+
+ public CrossEntityReference getCrossEntityReference() {
+ return crossEntityReference;
+ }
+
+ public void setCrossEntityReference(CrossEntityReference crossEntityReference) {
+ this.crossEntityReference = crossEntityReference;
+ }
+
+ /**
+ * Checks for cross entity references.
+ *
+ * @return true, if successful
+ */
+ public boolean hasCrossEntityReferences() {
+ if (this.crossEntityReference == null) {
+ return false;
+ }
+ if (!this.crossEntityReference.getReferenceAttributes().isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+
+ @Override
+ public String toString() {
+ return "CrossEntityReferenceDescriptor ["
+ + (crossEntityReference != null ? "crossEntityReference=" + crossEntityReference + ", "
+ : "")
+ + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceLookup.java b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceLookup.java
new file mode 100644
index 0000000..81fe943
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/CrossEntityReferenceLookup.java
@@ -0,0 +1,154 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public class CrossEntityReferenceLookup implements OxmModelProcessor {
+
+ // TODO: kill singleton collaborator pattern
+ private static CrossEntityReferenceLookup instance;
+
+ private Map> crossReferenceEntityOxmModel;
+ private Map crossReferenceEntityDescriptors;
+
+
+ private CrossEntityReferenceLookup() {
+ crossReferenceEntityOxmModel = new LinkedHashMap>();
+ crossReferenceEntityDescriptors = new HashMap();
+ }
+
+ public synchronized static CrossEntityReferenceLookup getInstance() {
+
+ /*
+ * I hate this method and I want it to go away. The singleton pattern is transitory, I want this
+ * class to be wired via a bean reference instead. But from the starting point, it would require
+ * fixing all the classes across the code base up front and I don't want this task to expand
+ * beyond just refactoring the OxmModelLoader. For now I'll keep the singleton pattern, but I
+ * really want to get rid of it once we are properly spring wired.
+ */
+
+ if (instance == null) {
+ instance = new CrossEntityReferenceLookup();
+ }
+
+ return instance;
+ }
+
+
+ @Override
+ public void processOxmModel(DynamicJAXBContext jaxbContext) {
+
+ @SuppressWarnings("rawtypes")
+ List descriptorsList = jaxbContext.getXMLContext().getDescriptors();
+
+ for (@SuppressWarnings("rawtypes")
+ Descriptor desc : descriptorsList) {
+
+ DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
+
+ LinkedHashMap oxmProperties = new LinkedHashMap();
+
+ // Not all fields have key attributes
+ if (desc.getPrimaryKeyFields() != null) {
+ oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
+ .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
+ }
+
+ String entityName = desc.getDefaultRootElement();
+
+ // add entityName
+ oxmProperties.put("entityName", entityName);
+
+ Map properties = entity.getDescriptor().getProperties();
+ if (properties != null) {
+ for (Map.Entry entry : properties.entrySet()) {
+
+ if (entry.getKey().equalsIgnoreCase("crossEntityReference")) {
+ oxmProperties.put("crossEntityReference", entry.getValue());
+ }
+ }
+ }
+
+ if (oxmProperties.containsKey("crossEntityReference")) {
+ crossReferenceEntityOxmModel.put(entityName, oxmProperties);
+ }
+
+ }
+
+ for (Entry> crossRefModel : crossReferenceEntityOxmModel
+ .entrySet()) {
+ HashMap attribute = crossRefModel.getValue();
+ CrossEntityReferenceDescriptor entity = new CrossEntityReferenceDescriptor();
+ entity.setEntityName(attribute.get("entityName"));
+ entity.setPrimaryKeyAttributeNames(
+ Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
+
+ List crossEntityRefTokens =
+ Arrays.asList(attribute.get("crossEntityReference").split(","));
+
+ if (crossEntityRefTokens.size() >= 2) {
+ CrossEntityReference entityRef = new CrossEntityReference();
+ entityRef.setTargetEntityType(crossEntityRefTokens.get(0));
+
+ for (int i = 1; i < crossEntityRefTokens.size(); i++) {
+ entityRef.addReferenceAttribute(crossEntityRefTokens.get(i));
+ }
+
+ entity.setCrossEntityReference(entityRef);
+ }
+ crossReferenceEntityDescriptors.put(attribute.get("entityName"), entity);
+ }
+
+ }
+
+ public Map> getCrossReferenceEntityOxmModel() {
+ return crossReferenceEntityOxmModel;
+ }
+
+ public void setCrossReferenceEntityOxmModel(
+ Map> crossReferenceEntityOxmModel) {
+ this.crossReferenceEntityOxmModel = crossReferenceEntityOxmModel;
+ }
+
+ public Map getCrossReferenceEntityDescriptors() {
+ return crossReferenceEntityDescriptors;
+ }
+
+ public void setCrossReferenceEntityDescriptors(
+ Map crossReferenceEntityDescriptors) {
+ this.crossReferenceEntityDescriptors = crossReferenceEntityDescriptors;
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityDescriptor.java
new file mode 100644
index 0000000..5a45842
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityDescriptor.java
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+public class GeoEntityDescriptor extends OxmEntityDescriptor {
+
+ protected String geoLatName;
+
+ protected String geoLongName;
+
+ public String getGeoLatName() {
+ return geoLatName;
+ }
+
+ public void setGeoLatName(String geoLatName) {
+ this.geoLatName = geoLatName;
+ }
+
+ public String getGeoLongName() {
+ return geoLongName;
+ }
+
+ public void setGeoLongName(String geoLongName) {
+ this.geoLongName = geoLongName;
+ }
+
+ @Override
+ public String toString() {
+ return "GeoEntityDescriptor [" + (geoLatName != null ? "geoLatName=" + geoLatName + ", " : "")
+ + (geoLongName != null ? "geoLongName=" + geoLongName + ", " : "")
+ + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityLookup.java b/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityLookup.java
new file mode 100644
index 0000000..f8b1ceb
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/GeoEntityLookup.java
@@ -0,0 +1,155 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public class GeoEntityLookup implements OxmModelProcessor {
+
+ // TODO: kill singleton collaborator pattern
+ private static GeoEntityLookup instance;
+
+ private Map> geoEntityOxmModel;
+
+ private Map geoEntityDescriptors;
+
+ private GeoEntityLookup() {
+ geoEntityOxmModel = new LinkedHashMap>();
+ geoEntityDescriptors = new HashMap();
+ }
+
+ public synchronized static GeoEntityLookup getInstance() {
+
+ /*
+ * I hate this method and I want it to go away. The singleton pattern is transitory, I want this
+ * class to be wired via a bean reference instead. But from the starting point, it would require
+ * fixing all the classes across the code base up front and I don't want this task to expand
+ * beyond just refactoring the OxmModelLoader. For now I'll keep the singleton pattern, but I
+ * really want to get rid of it once we are properly spring wired.
+ */
+
+ if (instance == null) {
+ instance = new GeoEntityLookup();
+ }
+
+ return instance;
+ }
+
+ public Map> getGeoEntityOxmModel() {
+ return geoEntityOxmModel;
+ }
+
+ public void setGeoEntityOxmModel(Map> geoEntityOxmModel) {
+ this.geoEntityOxmModel = geoEntityOxmModel;
+ }
+
+ public Map getGeoEntityDescriptors() {
+ return geoEntityDescriptors;
+ }
+
+ public void setGeoEntityDescriptors(Map geoEntityDescriptors) {
+ this.geoEntityDescriptors = geoEntityDescriptors;
+ }
+
+ @Override
+ public void processOxmModel(DynamicJAXBContext jaxbContext) {
+
+ @SuppressWarnings("rawtypes")
+ List descriptorsList = jaxbContext.getXMLContext().getDescriptors();
+
+ for (@SuppressWarnings("rawtypes")
+ Descriptor desc : descriptorsList) {
+
+ DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
+
+ LinkedHashMap oxmProperties = new LinkedHashMap();
+
+ // Not all fields have key attributes
+ if (desc.getPrimaryKeyFields() != null) {
+ oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
+ .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
+ }
+
+ String entityName = desc.getDefaultRootElement();
+
+ // add entityName
+ oxmProperties.put("entityName", entityName);
+
+ Map properties = entity.getDescriptor().getProperties();
+
+ if (properties != null) {
+ for (Map.Entry entry : properties.entrySet()) {
+
+ if (entry.getKey().equalsIgnoreCase("geoLat")) {
+ if (entry.getValue().length() > 0) {
+ oxmProperties.put("geoLat", entry.getValue());
+ }
+ } else if (entry.getKey().equalsIgnoreCase("geoLong")) {
+ if (entry.getValue().length() > 0) {
+ oxmProperties.put("geoLong", entry.getValue());
+ }
+ }
+ }
+ }
+
+ if (oxmProperties.containsKey("geoLat") && oxmProperties.containsKey("geoLong")) {
+ geoEntityOxmModel.put(entityName, oxmProperties);
+ }
+
+ }
+
+ for (Entry> entityModel : geoEntityOxmModel.entrySet()) {
+
+ HashMap attribute = entityModel.getValue();
+
+ GeoOxmEntityDescriptor entity = new GeoOxmEntityDescriptor();
+
+ entity.setEntityName(attribute.get("entityName"));
+
+ if (attribute.containsKey("primaryKeyAttributeNames")) {
+
+ entity.setPrimaryKeyAttributeNames(
+ Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
+
+ if (attribute.containsKey("geoLat") || attribute.containsKey("geoLong")) {
+ entity.setGeoLatName(attribute.get("geoLat"));
+ entity.setGeoLongName(attribute.get("geoLong"));
+ }
+
+ geoEntityDescriptors.put(attribute.get("entityName"), entity);
+ }
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/GeoOxmEntityDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/GeoOxmEntityDescriptor.java
new file mode 100644
index 0000000..595c81a
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/GeoOxmEntityDescriptor.java
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+public class GeoOxmEntityDescriptor extends OxmEntityDescriptor {
+
+ private String geoLatName;
+
+ private String geoLongName;
+
+ public String getGeoLatName() {
+ return geoLatName;
+ }
+
+ public void setGeoLatName(String geoLatName) {
+ this.geoLatName = geoLatName;
+ }
+
+ public String getGeoLongName() {
+ return geoLongName;
+ }
+
+ public void setGeoLongName(String geoLongName) {
+ this.geoLongName = geoLongName;
+ }
+
+ /**
+ * Checks for geo entity.
+ *
+ * @return true, if successful
+ */
+ public boolean hasGeoEntity() {
+ return (this.geoLongName != null && this.geoLatName != null);
+ }
+
+ @Override
+ public String toString() {
+ return "GeoOxmEntityDescriptor ["
+ + (geoLatName != null ? "geoLatName=" + geoLatName + ", " : "")
+ + (geoLongName != null ? "geoLongName=" + geoLongName + ", " : "")
+ + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityDescriptor.java
index 379cca2..3b3fabd 100644
--- a/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityDescriptor.java
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityDescriptor.java
@@ -22,28 +22,18 @@
*/
package org.onap.aai.sparky.config.oxm;
+import java.util.ArrayList;
import java.util.List;
-import org.onap.aai.sparky.synchronizer.entity.SuggestionSearchEntity;
-
-/**
- * The Class OxmEntityDescriptor.
- */
public class OxmEntityDescriptor {
- private String entityName;
-
- private List primaryKeyAttributeName;
-
- private List searchableAttributes;
-
- private CrossEntityReference crossEntityReference;
+ protected String entityName;
- private String geoLatName;
+ protected List primaryKeyAttributeNames;
- private String geoLongName;
-
- private SuggestionSearchEntity suggestionSearchEntity;
+ public OxmEntityDescriptor() {
+ primaryKeyAttributeNames = new ArrayList();
+ }
public String getEntityName() {
return entityName;
@@ -53,124 +43,24 @@ public class OxmEntityDescriptor {
this.entityName = entityName;
}
- public List getPrimaryKeyAttributeName() {
- return primaryKeyAttributeName;
- }
-
- public void setPrimaryKeyAttributeName(List primaryKeyAttributeName) {
- this.primaryKeyAttributeName = primaryKeyAttributeName;
- }
-
- public List getSearchableAttributes() {
- return searchableAttributes;
- }
-
- public void setSearchableAttributes(List searchableAttributes) {
- this.searchableAttributes = searchableAttributes;
- }
-
- /**
- * Checks for searchable attributes.
- *
- * @return true, if successful
- */
- public boolean hasSearchableAttributes() {
-
- if (this.searchableAttributes == null) {
- return false;
- }
-
- if (this.searchableAttributes.size() > 0) {
- return true;
- }
-
- return false;
-
- }
-
- public CrossEntityReference getCrossEntityReference() {
- return crossEntityReference;
- }
-
- public void setCrossEntityReference(CrossEntityReference crossEntityReference) {
- this.crossEntityReference = crossEntityReference;
+ public List getPrimaryKeyAttributeNames() {
+ return primaryKeyAttributeNames;
}
- /**
- * Checks for cross entity references.
- *
- * @return true, if successful
- */
- public boolean hasCrossEntityReferences() {
- if (this.crossEntityReference == null) {
- return false;
- }
- if (!this.crossEntityReference.getReferenceAttributes().isEmpty()) {
- return true;
- }
- return false;
+ public void setPrimaryKeyAttributeNames(List primaryKeyAttributeNames) {
+ this.primaryKeyAttributeNames = primaryKeyAttributeNames;
}
- public String getGeoLatName() {
- return geoLatName;
- }
-
- public void setGeoLatName(String geoLatName) {
- this.geoLatName = geoLatName;
- }
-
- public String getGeoLongName() {
- return geoLongName;
- }
-
- public void setGeoLongName(String geoLongName) {
- this.geoLongName = geoLongName;
- }
-
- /**
- * Checks for geo entity.
- *
- * @return true, if successful
- */
- public boolean hasGeoEntity() {
-
- if (this.geoLongName != null && this.geoLatName != null) {
- return true;
- }
-
- return false;
-
- }
-
- public SuggestionSearchEntity getSuggestionSearchEntity() {
- return this.suggestionSearchEntity;
- }
-
- public void setSuggestionSearchEntity(SuggestionSearchEntity suggestionSearchEntity) {
- this.suggestionSearchEntity = suggestionSearchEntity;
- }
-
- /**
- * Checks for non-null, populated SuggestionSearchEntity.
- *
- * @return true, if successful
- */
- public boolean hasSuggestionSearchEntity() {
- if (this.suggestionSearchEntity == null) {
- return false;
- }
- if (!this.suggestionSearchEntity.getSuggestionConnectorWords().isEmpty()) {
- return true;
- }
- return false;
+ public void addPrimaryKeyName(String name) {
+ primaryKeyAttributeNames.add(name);
}
@Override
public String toString() {
- return "OxmEntityDescriptor [entityName=" + entityName + ", primaryKeyAttributeName="
- + primaryKeyAttributeName + ", searchableAttributes=" + searchableAttributes
- + ", crossEntityReference=" + crossEntityReference + ", geoLatName=" + geoLatName
- + ", geoLongName=" + geoLongName + ", suggestionSearchEntity=" + suggestionSearchEntity
+ return "OxmEntityDescriptor [" + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ "]";
}
+
}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityLookup.java b/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityLookup.java
new file mode 100644
index 0000000..168a4b1
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/OxmEntityLookup.java
@@ -0,0 +1,151 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public class OxmEntityLookup implements OxmModelProcessor {
+
+ // TODO: kill singleton collaborator pattern
+ private static OxmEntityLookup instance;
+
+ private Map> oxmModel;
+
+ private Map entityTypeLookup;
+
+ private Map entityDescriptors;
+
+
+ private OxmEntityLookup() {
+ oxmModel = new LinkedHashMap>();
+ entityTypeLookup = new LinkedHashMap();
+ entityDescriptors = new HashMap();
+ }
+
+ public synchronized static OxmEntityLookup getInstance() {
+
+ /*
+ * I hate this method and I want it to go away. The singleton pattern is transitory, I want this
+ * class to be wired via a bean reference instead. But from the starting point, it would require
+ * fixing all the classes across the code base up front and I don't want this task to expand
+ * beyond just refactoring the OxmModelLoader. For now I'll keep the singleton pattern, but I
+ * really want to get rid of it once we are properly spring wired.
+ */
+
+ if (instance == null) {
+ instance = new OxmEntityLookup();
+ }
+
+ return instance;
+ }
+
+
+ @Override
+ public void processOxmModel(DynamicJAXBContext jaxbContext) {
+
+ @SuppressWarnings("rawtypes")
+ List descriptorsList = jaxbContext.getXMLContext().getDescriptors();
+
+ for (@SuppressWarnings("rawtypes")
+ Descriptor desc : descriptorsList) {
+
+ DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
+
+ LinkedHashMap oxmProperties = new LinkedHashMap();
+
+ // Not all fields have key attributes
+ if (desc.getPrimaryKeyFields() != null) {
+ oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
+ .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
+ }
+
+ String entityName = desc.getDefaultRootElement();
+
+ entityTypeLookup.put(entityName, entity);
+
+ // add entityName
+ oxmProperties.put("entityName", entityName);
+
+ Map properties = entity.getDescriptor().getProperties();
+
+ oxmModel.put(entityName, oxmProperties);
+
+ }
+
+ for (Entry> entityModel : oxmModel.entrySet()) {
+ HashMap attribute = entityModel.getValue();
+ OxmEntityDescriptor entity = new OxmEntityDescriptor();
+
+ entity.setEntityName(attribute.get("entityName"));
+
+ if (attribute.containsKey("primaryKeyAttributeNames")) {
+
+ entity.setPrimaryKeyAttributeNames(
+ Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
+
+ entityDescriptors.put(attribute.get("entityName"), entity);
+ }
+ }
+
+ }
+
+ public Map> getOxmModel() {
+ return oxmModel;
+ }
+
+ public void setOxmModel(Map> oxmModel) {
+ this.oxmModel = oxmModel;
+ }
+
+ public Map getEntityTypeLookup() {
+ return entityTypeLookup;
+ }
+
+ public void setEntityTypeLookup(Map entityTypeLookup) {
+ this.entityTypeLookup = entityTypeLookup;
+ }
+
+ public Map getEntityDescriptors() {
+ return entityDescriptors;
+ }
+
+ public void setEntityDescriptors(Map entityDescriptors) {
+ this.entityDescriptors = entityDescriptors;
+ }
+
+ public void addEntityDescriptor(String type, OxmEntityDescriptor descriptor) {
+ if (this.entityDescriptors != null) {
+ this.entityDescriptors.put(type, descriptor);
+ }
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoader.java b/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoader.java
index 853a537..b953917 100644
--- a/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoader.java
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoader.java
@@ -22,485 +22,163 @@
*/
package org.onap.aai.sparky.config.oxm;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Vector;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.eclipse.persistence.dynamic.DynamicType;
-import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
-import org.eclipse.persistence.mappings.DatabaseMapping;
-import org.onap.aai.sparky.logging.AaiUiMsgs;
-import org.onap.aai.sparky.synchronizer.entity.SuggestionSearchEntity;
-import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
import org.onap.aai.cl.api.Logger;
import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
-/**
- * The Class OxmModelLoader.
- */
public class OxmModelLoader {
- private static OxmModelLoader instance;
-
private static final Logger LOG = LoggerFactory.getInstance().getLogger(OxmModelLoader.class);
- private Map> oxmModel =
- new LinkedHashMap>();
-
- private Map entityTypeLookup = new LinkedHashMap();
-
- private Map> searchableOxmModel =
- new LinkedHashMap>();
-
- private Map> crossReferenceEntityOxmModel =
- new LinkedHashMap>();
-
- private Map> geoEntityOxmModel =
- new LinkedHashMap>();
-
- private Map> suggestionSearchEntityOxmModel =
- new LinkedHashMap>();
-
- private Map entityDescriptors =
- new HashMap();
-
- private Map searchableEntityDescriptors =
- new HashMap();
-
- private Map crossReferenceEntityDescriptors =
- new HashMap();
-
- private Map geoEntityDescriptors =
- new HashMap();
-
- private Map suggestionSearchEntityDescriptors =
- new HashMap();
-
- public static OxmModelLoader getInstance() {
- if (instance == null) {
- instance = new OxmModelLoader();
- LOG.info(AaiUiMsgs.INITIALIZE_OXM_MODEL_LOADER);
- instance.loadModels();
- }
+ /*
+ * The intent of this parameter is to be able to programmatically over-ride the latest AAI schema
+ * version discovered from the aai-schema jar file. This property is optional, but if set on the
+ * bean or by another class in the system, then it will override the spec version that is loaded.
+ *
+ * If the latestVersionOverride is greater than 0 then it will set the latest version to the
+ * specified version, and that stream will be returned if available.
+ */
- return instance;
+ protected int oxmApiVersionOverride;
+ protected Set processors;
+ private int latestVersionNum = 0;
- }
+ private final static Pattern p = Pattern.compile("aai_oxm_(v)(.*).xml");
- /**
- * Instantiates a new oxm model loader.
- */
public OxmModelLoader() {
+ this(-1, new HashSet());
+ }
+ public OxmModelLoader(int apiVersionOverride, Set oxmModelProcessors) {
+ this.oxmApiVersionOverride = apiVersionOverride;
+ this.processors = oxmModelProcessors;
}
- /**
- * Load models.
- */
- private void loadModels() {
- // find latest version of OXM file in folder
- String version = findLatestOxmVersion();
- if (version == null) {
- LOG.error(AaiUiMsgs.OXM_FILE_NOT_FOUND, TierSupportUiConstants.CONFIG_OXM_LOCATION);
- return;
+ protected synchronized Map getStreamHandlesForOxmFromResource() {
+ Map listOfOxmFiles = new HashMap();
+ ClassLoader oxmClassLoader = OxmModelLoader.class.getClassLoader();
+ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(oxmClassLoader);
+ Resource[] resources = null;
+ try {
+ resources = resolver.getResources("classpath*:/oxm/aai_oxm*.xml");
+ } catch (IOException ex) {
+ LOG.error(AaiUiMsgs.OXM_LOADING_ERROR, ex.getMessage());
}
- // load the latest version based on file name
- loadModel(version);
+ if (resources == null) {
+ LOG.error(AaiUiMsgs.OXM_LOADING_ERROR, "No OXM schema files found on classpath");
+ }
+
+ for (Resource resource : resources) {
+ Matcher m = p.matcher(resource.getFilename());
+ if (m.matches()) {
+ try {
+ listOfOxmFiles.put(new Integer(m.group(2)), resource.getInputStream());
+ } catch (Exception e) {
+ LOG.error(AaiUiMsgs.OXM_LOADING_ERROR, resource.getFilename(), e.getMessage());
+ }
+ }
+ }
+ return listOfOxmFiles;
}
/**
- * Load model.
- *
- * @param version the version
+ * Load an oxm model.
+ *
+ * @param inputStream file handle for oxm
*/
- public void loadModel(String version) {
- String fileName = loadOxmFileName(version);
-
- try (FileInputStream inputStream = new FileInputStream(new File(fileName))) {
- Map properties = new HashMap();
- properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, inputStream);
-
+ protected void loadModel(InputStream inputStream) {
+ Map properties = new HashMap();
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, inputStream);
+ try {
final DynamicJAXBContext oxmContext = DynamicJAXBContextFactory
.createContextFromOXM(Thread.currentThread().getContextClassLoader(), properties);
+
parseOxmContext(oxmContext);
// populateSearchableOxmModel();
- LOG.info(AaiUiMsgs.OXM_LOAD_SUCCESS);
-
- } catch (FileNotFoundException fnf) {
- LOG.info(AaiUiMsgs.OXM_READ_ERROR_NONVERBOSE);
- LOG.error(AaiUiMsgs.OXM_READ_ERROR_VERBOSE, fileName);
+ LOG.info(AaiUiMsgs.OXM_LOAD_SUCCESS, String.valueOf(latestVersionNum));
} catch (Exception exc) {
LOG.info(AaiUiMsgs.OXM_PARSE_ERROR_NONVERBOSE);
- LOG.error(AaiUiMsgs.OXM_PARSE_ERROR_VERBOSE, fileName, exc.getMessage());
+ LOG.error(AaiUiMsgs.OXM_PARSE_ERROR_VERBOSE, "OXM v" + latestVersionNum, exc.getMessage());
}
}
/**
- * Parses the oxm context.
- *
- * @param oxmContext the oxm context
+ * Load the latest oxm model.
*/
- private void parseOxmContext(DynamicJAXBContext oxmContext) {
- @SuppressWarnings("rawtypes")
- List descriptorsList = oxmContext.getXMLContext().getDescriptors();
-
- for (@SuppressWarnings("rawtypes")
- Descriptor desc : descriptorsList) {
-
- DynamicType entity = oxmContext.getDynamicType(desc.getAlias());
-
- LinkedHashMap oxmProperties = new LinkedHashMap();
-
- // Not all fields have key attributes
- if (desc.getPrimaryKeyFields() != null) {
- oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
- .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
- }
-
- String entityName = desc.getDefaultRootElement();
-
- entityTypeLookup.put(entityName, entity);
-
- // add entityName
- oxmProperties.put("entityName", entityName);
-
- Map properties = entity.getDescriptor().getProperties();
- if (properties != null) {
- for (Map.Entry entry : properties.entrySet()) {
-
- if (entry.getKey().equalsIgnoreCase("searchable")) {
- oxmProperties.put("searchableAttributes", entry.getValue());
- } else if (entry.getKey().equalsIgnoreCase("crossEntityReference")) {
- oxmProperties.put("crossEntityReference", entry.getValue());
- } else if (entry.getKey().equalsIgnoreCase("geoLat")) {
- if (entry.getValue().length() > 0) {
- oxmProperties.put("geoLat", entry.getValue());
- }
- } else if (entry.getKey().equalsIgnoreCase("geoLong")) {
- if (entry.getValue().length() > 0) {
- oxmProperties.put("geoLong", entry.getValue());
- }
- } else if (entry.getKey().equalsIgnoreCase("containsSuggestibleProps")) {
-
- oxmProperties.put("containsSuggestibleProps", "true");
-
- Vector descriptorMaps = entity.getDescriptor().getMappings();
- List listOfSuggestableAttributes = new ArrayList();
-
- for (DatabaseMapping descMap : descriptorMaps) {
- if (descMap.isAbstractDirectMapping()) {
-
- if (descMap.getProperties().get("suggestibleOnSearch") != null) {
- String suggestableOnSearchString =
- String.valueOf(descMap.getProperties().get("suggestibleOnSearch"));
-
- boolean isSuggestibleOnSearch = Boolean.valueOf(suggestableOnSearchString);
-
- if (isSuggestibleOnSearch) {
- /* Grab attribute types for suggestion */
- String attributeName =
- descMap.getField().getName().replaceAll("/text\\(\\)", "");
- listOfSuggestableAttributes.add(attributeName);
-
- if (descMap.getProperties().get("suggestionVerbs") != null) {
- String suggestionVerbsString =
- String.valueOf(descMap.getProperties().get("suggestionVerbs"));
-
- oxmProperties.put("suggestionVerbs", suggestionVerbsString);
- }
- }
- }
- }
- }
- if (!listOfSuggestableAttributes.isEmpty()) {
- oxmProperties.put("suggestibleAttributes",
- String.join(",", listOfSuggestableAttributes));
- }
- } else if (entry.getKey().equalsIgnoreCase("suggestionAliases")) {
- oxmProperties.put("suggestionAliases", entry.getValue());
- }
- }
- }
-
- oxmModel.put(entityName, oxmProperties);
-
- // Add all searchable entity types for reserve lookup
- if (oxmProperties.containsKey("searchableAttributes")) {
- searchableOxmModel.put(entityName, oxmProperties);
- }
+ public synchronized void loadLatestOxmModel() {
- if (oxmProperties.containsKey("crossEntityReference")) {
- crossReferenceEntityOxmModel.put(entityName, oxmProperties);
- }
-
- if (oxmProperties.containsKey("geoLat") && oxmProperties.containsKey("geoLong")) {
- geoEntityOxmModel.put(entityName, oxmProperties);
- }
-
- if (oxmProperties.containsKey("containsSuggestibleProps")) {
- suggestionSearchEntityOxmModel.put(entityName, oxmProperties);
- }
- }
-
- for (Entry> entityModel : oxmModel.entrySet()) {
- HashMap attribute = entityModel.getValue();
- OxmEntityDescriptor entity = new OxmEntityDescriptor();
- entity.setEntityName(attribute.get("entityName"));
- if (attribute.containsKey("primaryKeyAttributeNames")) {
-
- entity.setPrimaryKeyAttributeName(
- Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
- if (attribute.containsKey("searchableAttributes")) {
- entity.setSearchableAttributes(
- Arrays.asList(attribute.get("searchableAttributes").split(",")));
- } else if (attribute.containsKey("crossEntityReference")) {
- List crossEntityRefTokens =
- Arrays.asList(attribute.get("crossEntityReference").split(","));
-
- if (crossEntityRefTokens.size() >= 2) {
- CrossEntityReference entityRef = new CrossEntityReference();
- entityRef.setTargetEntityType(crossEntityRefTokens.get(0));
-
- for (int i = 1; i < crossEntityRefTokens.size(); i++) {
- entityRef.addReferenceAttribute(crossEntityRefTokens.get(i));
- }
-
- entity.setCrossEntityReference(entityRef);
- } else {
- LOG.error(AaiUiMsgs.OXM_PROP_DEF_ERR_CROSS_ENTITY_REF, attribute.get("entityName"),
- attribute.get("crossEntityReference"));
- }
- }
-
- if (attribute.containsKey("geoLat") || attribute.containsKey("geoLong")) {
- entity.setGeoLatName(attribute.get("geoLat"));
- entity.setGeoLongName(attribute.get("geoLong"));
- }
-
- if (attribute.containsKey("suggestionVerbs")) {
- String entityName = attribute.get("entityName");
- SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity(this);
- suggestionSearchEntity.setEntityType(entityName);
-
- entity.setSuggestionSearchEntity(suggestionSearchEntity);
- }
-
- entityDescriptors.put(attribute.get("entityName"), entity);
- }
- }
+ LOG.info(AaiUiMsgs.INITIALIZE_OXM_MODEL_LOADER);
-
- for (Entry> searchableModel : searchableOxmModel.entrySet()) {
- HashMap attribute = searchableModel.getValue();
- OxmEntityDescriptor entity = new OxmEntityDescriptor();
- entity.setEntityName(attribute.get("entityName"));
- entity.setPrimaryKeyAttributeName(
- Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
- entity
- .setSearchableAttributes(Arrays.asList(attribute.get("searchableAttributes").split(",")));
- searchableEntityDescriptors.put(attribute.get("entityName"), entity);
- }
-
- for (Entry> geoEntityModel : geoEntityOxmModel.entrySet()) {
- HashMap attribute = geoEntityModel.getValue();
- OxmEntityDescriptor entity = new OxmEntityDescriptor();
- entity.setEntityName(attribute.get("entityName"));
- entity.setPrimaryKeyAttributeName(
- Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
- entity.setGeoLatName(attribute.get("geoLat"));
- entity.setGeoLongName(attribute.get("geoLong"));
- geoEntityDescriptors.put(attribute.get("entityName"), entity);
+ // find handles for available oxm models
+ final Map listOfOxmStreams = getStreamHandlesForOxmFromResource();
+ if (listOfOxmStreams.isEmpty()) {
+ LOG.error(AaiUiMsgs.OXM_FILE_NOT_FOUND);
+ return;
}
- for (Entry> crossRefModel : crossReferenceEntityOxmModel
- .entrySet()) {
- HashMap attribute = crossRefModel.getValue();
- OxmEntityDescriptor entity = new OxmEntityDescriptor();
- entity.setEntityName(attribute.get("entityName"));
- entity.setPrimaryKeyAttributeName(
- Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
-
+ InputStream stream = null;
- List crossEntityRefTokens =
- Arrays.asList(attribute.get("crossEntityReference").split(","));
-
- if (crossEntityRefTokens.size() >= 2) {
- CrossEntityReference entityRef = new CrossEntityReference();
- entityRef.setTargetEntityType(crossEntityRefTokens.get(0));
+ if (oxmApiVersionOverride > 0) {
+ latestVersionNum = oxmApiVersionOverride;
+ LOG.warn(AaiUiMsgs.WARN_GENERIC, "Overriding AAI Schema with version = " + latestVersionNum);
+ stream = listOfOxmStreams.get(latestVersionNum);
+ } else {
- for (int i = 1; i < crossEntityRefTokens.size(); i++) {
- entityRef.addReferenceAttribute(crossEntityRefTokens.get(i));
+ for (Integer key : listOfOxmStreams.keySet()) {
+ if (key.intValue() > latestVersionNum) {
+ latestVersionNum = key.intValue();
+ stream = listOfOxmStreams.get(key);
}
-
- entity.setCrossEntityReference(entityRef);
}
- crossReferenceEntityDescriptors.put(attribute.get("entityName"), entity);
}
- for (Entry> suggestionEntityModel : suggestionSearchEntityOxmModel
- .entrySet()) {
- HashMap attribute = suggestionEntityModel.getValue();
-
- String entityName = attribute.get("entityName");
- SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity(this);
- suggestionSearchEntity.setEntityType(entityName);
+ // load the latest oxm file
+ loadModel(stream);
- if (attribute.get("suggestionVerbs") != null) {
- suggestionSearchEntity.setSuggestionConnectorWords(
- Arrays.asList(attribute.get("suggestionVerbs").split(",")));
- }
-
- if (attribute.get("suggestionAliases") != null) {
- suggestionSearchEntity
- .setSuggestionAliases(Arrays.asList(attribute.get("suggestionAliases").split(",")));
- }
-
- if (attribute.get("suggestibleAttributes") != null) {
- suggestionSearchEntity.setSuggestionPropertyTypes(
- Arrays.asList(attribute.get("suggestibleAttributes").split(",")));
- }
-
- OxmEntityDescriptor entity = new OxmEntityDescriptor();
- entity.setSuggestionSearchEntity(suggestionSearchEntity);
- entity.setEntityName(entityName);
-
- if (attribute.get("primaryKeyAttributeNames") != null) {
- entity.setPrimaryKeyAttributeName(
- Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
- }
-
- suggestionSearchEntityDescriptors.put(entityName, entity);
- }
}
- /**
- * Find latest oxm version.
- *
- * @return the string
- */
- public String findLatestOxmVersion() {
- File[] listOxmFiles = loadOxmFolder().listFiles();
-
- if (listOxmFiles == null) {
- return null;
- }
-
- Integer latestVersion = -1;
-
- Pattern oxmFileNamePattern = Pattern.compile("^aai_oxm_v([0-9]*).xml");
-
- for (File file : listOxmFiles) {
- if (file.isFile()) {
- String fileName = file.getName();
- Matcher matcher = oxmFileNamePattern.matcher(fileName);
- if (matcher.matches()) {
- if (latestVersion <= Integer.parseInt(matcher.group(1))) {
- latestVersion = Integer.parseInt(matcher.group(1));
- }
- }
- }
-
- }
- if (latestVersion != -1) {
- return "v" + latestVersion.toString();
- } else {
- return null;
- }
-
+ public int getLatestVersionNum() {
+ return latestVersionNum;
}
- /**
- * Load oxm folder.
- *
- * @return the file
- */
- public File loadOxmFolder() {
- return new File(TierSupportUiConstants.CONFIG_OXM_LOCATION);
+ public void setLatestVersionNum(int latestVersionNum) {
+ this.latestVersionNum = latestVersionNum;
}
/**
- * Load oxm file name.
+ * Parses the oxm context.
*
- * @param version the version
- * @return the string
- */
- public String loadOxmFileName(String version) {
- return new String(TierSupportUiConstants.CONFIG_OXM_LOCATION + "aai_oxm_" + version + ".xml");
- }
-
- /*
- * Get the original representation of the OXM Model
- */
- public Map> getOxmModel() {
- return oxmModel;
- }
-
- /*
- * Get the searchable raw map entity types
+ * @param oxmContext the oxm context
*/
- public Map> getSearchableOxmModel() {
- return searchableOxmModel;
- }
-
- public Map> getCrossReferenceEntityOxmModel() {
- return crossReferenceEntityOxmModel;
- }
-
- public Map getEntityDescriptors() {
- return entityDescriptors;
- }
+ private void parseOxmContext(DynamicJAXBContext oxmContext) {
- /**
- * Gets the entity descriptor.
- *
- * @param type the type
- * @return the entity descriptor
- */
- public OxmEntityDescriptor getEntityDescriptor(String type) {
- return entityDescriptors.get(type);
- }
+ if (processors != null && processors.size() > 0) {
- public Map getSearchableEntityDescriptors() {
- return searchableEntityDescriptors;
- }
+ for (OxmModelProcessor processor : processors) {
- /**
- * Gets the searchable entity descriptor.
- *
- * @param entityType the entity type
- * @return the searchable entity descriptor
- */
- public OxmEntityDescriptor getSearchableEntityDescriptor(String entityType) {
- return searchableEntityDescriptors.get(entityType);
- }
+ processor.processOxmModel(oxmContext);
- public Map getCrossReferenceEntityDescriptors() {
- return crossReferenceEntityDescriptors;
- }
+ }
- public Map getGeoEntityDescriptors() {
- return geoEntityDescriptors;
- }
+ }
- public Map getSuggestionSearchEntityDescriptors() {
- return suggestionSearchEntityDescriptors;
}
}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderFilter.java b/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderFilter.java
deleted file mode 100644
index 0ddf80a..0000000
--- a/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelLoaderFilter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-package org.onap.aai.sparky.config.oxm;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-import org.onap.aai.sparky.util.NodeUtils;
-import org.onap.aai.cl.mdc.MdcContext;
-
-/**
- * The Class OxmModelLoaderFilter.
- */
-public class OxmModelLoaderFilter implements Filter {
- /*
- * (non-Javadoc)
- *
- * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
- * javax.servlet.FilterChain)
- */
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-
- /*
- * However, we will setup the filtermap with a url that should never get it, so we shouldn't
- * ever be in here.
- */
-
- chain.doFilter(request, response);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
- */
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- String txnID = NodeUtils.getRandomTxnId();
- MdcContext.initialize(txnID, "OxmModelLoaderFilter", "", "Init", "");
-
- try {
- OxmModelLoader.getInstance();
- } catch (Exception exc) {
- throw new ServletException("Caught an exception while initializing OXM model loader filter",
- exc);
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see javax.servlet.Filter#destroy()
- */
- @Override
- public void destroy() {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelProcessor.java b/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelProcessor.java
new file mode 100644
index 0000000..b8e7c6f
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/OxmModelProcessor.java
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public interface OxmModelProcessor {
+
+ public void processOxmModel(DynamicJAXBContext jaxbContext);
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/SearchableEntityLookup.java b/src/main/java/org/onap/aai/sparky/config/oxm/SearchableEntityLookup.java
new file mode 100644
index 0000000..d8a27ac
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/SearchableEntityLookup.java
@@ -0,0 +1,138 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public class SearchableEntityLookup implements OxmModelProcessor {
+
+ // TODO: kill singleton collaborator pattern
+ private static SearchableEntityLookup instance;
+
+ private Map> searchableOxmModel;
+ private Map searchableEntityDescriptors;
+
+ private SearchableEntityLookup() {
+ searchableOxmModel = new LinkedHashMap>();
+ searchableEntityDescriptors = new HashMap();
+ }
+
+ public synchronized static SearchableEntityLookup getInstance() {
+
+ /*
+ * I hate this method and I want it to go away. The singleton pattern is transitory, I want this
+ * class to be wired via a bean reference instead. But from the starting point, it would require
+ * fixing all the classes across the code base up front and I don't want this task to expand
+ * beyond just refactoring the OxmModelLoader. For now I'll keep the singleton pattern, but I
+ * really want to get rid of it once we are properly spring wired.
+ */
+
+ if (instance == null) {
+ instance = new SearchableEntityLookup();
+ }
+
+ return instance;
+ }
+
+
+ @Override
+ public void processOxmModel(DynamicJAXBContext jaxbContext) {
+
+ @SuppressWarnings("rawtypes")
+ List descriptorsList = jaxbContext.getXMLContext().getDescriptors();
+
+ for (@SuppressWarnings("rawtypes")
+ Descriptor desc : descriptorsList) {
+
+ DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
+
+ LinkedHashMap oxmProperties = new LinkedHashMap();
+
+ // Not all fields have key attributes
+ if (desc.getPrimaryKeyFields() != null) {
+ oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
+ .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
+ }
+
+ String entityName = desc.getDefaultRootElement();
+
+ // add entityName
+ oxmProperties.put("entityName", entityName);
+
+ Map properties = entity.getDescriptor().getProperties();
+ if (properties != null) {
+ for (Map.Entry entry : properties.entrySet()) {
+
+ if (entry.getKey().equalsIgnoreCase("searchable")) {
+ oxmProperties.put("searchableAttributes", entry.getValue());
+ }
+ }
+ }
+
+ // Add all searchable entity types for reserve lookup
+ if (oxmProperties.containsKey("searchableAttributes")) {
+ searchableOxmModel.put(entityName, oxmProperties);
+ }
+
+ }
+
+ for (Entry> searchableModel : searchableOxmModel.entrySet()) {
+ HashMap attribute = searchableModel.getValue();
+ SearchableOxmEntityDescriptor entity = new SearchableOxmEntityDescriptor();
+ entity.setEntityName(attribute.get("entityName"));
+ entity.setPrimaryKeyAttributeNames(
+ Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
+ entity
+ .setSearchableAttributes(Arrays.asList(attribute.get("searchableAttributes").split(",")));
+ searchableEntityDescriptors.put(attribute.get("entityName"), entity);
+ }
+
+ }
+
+ public Map> getSearchableOxmModel() {
+ return searchableOxmModel;
+ }
+
+ public void setSearchableOxmModel(Map> searchableOxmModel) {
+ this.searchableOxmModel = searchableOxmModel;
+ }
+
+ public Map getSearchableEntityDescriptors() {
+ return searchableEntityDescriptors;
+ }
+
+ public void setSearchableEntityDescriptors(
+ Map searchableEntityDescriptors) {
+ this.searchableEntityDescriptors = searchableEntityDescriptors;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/SearchableOxmEntityDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/SearchableOxmEntityDescriptor.java
new file mode 100644
index 0000000..cdd5ad0
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/SearchableOxmEntityDescriptor.java
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.List;
+
+public class SearchableOxmEntityDescriptor extends OxmEntityDescriptor {
+
+ protected List searchableAttributes;
+
+ public List getSearchableAttributes() {
+ return searchableAttributes;
+ }
+
+ public void setSearchableAttributes(List searchableAttributes) {
+ this.searchableAttributes = searchableAttributes;
+ }
+
+ public void addSearchableAttribute(String attributeName) {
+ searchableAttributes.add(attributeName);
+ }
+
+ /**
+ * Checks for searchable attributes.
+ *
+ * @return true, if successful
+ */
+ public boolean hasSearchableAttributes() {
+
+ if (this.searchableAttributes == null) {
+ return false;
+ }
+
+ if (this.searchableAttributes.size() > 0) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+ @Override
+ public String toString() {
+ return "SearchableOxmEntityDescriptor ["
+ + (searchableAttributes != null ? "searchableAttributes=" + searchableAttributes + ", "
+ : "")
+ + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ + "]";
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityDescriptor.java b/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityDescriptor.java
new file mode 100644
index 0000000..c72068a
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityDescriptor.java
@@ -0,0 +1,52 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import org.onap.aai.sparky.sync.entity.SuggestionSearchEntity;
+
+public class SuggestionEntityDescriptor extends OxmEntityDescriptor {
+
+ protected SuggestionSearchEntity suggestionSearchEntity;
+
+ public SuggestionSearchEntity getSuggestionSearchEntity() {
+ return suggestionSearchEntity;
+ }
+
+ public void setSuggestionSearchEntity(SuggestionSearchEntity suggestionSearchEntity) {
+ this.suggestionSearchEntity = suggestionSearchEntity;
+ }
+
+ @Override
+ public String toString() {
+ return "SuggestionEntityDescriptor ["
+ + (suggestionSearchEntity != null
+ ? "suggestionSearchEntity=" + suggestionSearchEntity + ", " : "")
+ + (entityName != null ? "entityName=" + entityName + ", " : "")
+ + (primaryKeyAttributeNames != null ? "primaryKeyAttributeNames=" + primaryKeyAttributeNames
+ : "")
+ + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityLookup.java b/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityLookup.java
new file mode 100644
index 0000000..758ae60
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/config/oxm/SuggestionEntityLookup.java
@@ -0,0 +1,197 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.config.oxm;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Vector;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.onap.aai.sparky.sync.entity.SuggestionSearchEntity;
+
+public class SuggestionEntityLookup implements OxmModelProcessor {
+
+ // TODO: kill singleton collaborator pattern
+ private static SuggestionEntityLookup instance;
+
+ private Map> suggestionSearchEntityOxmModel;
+ private Map suggestionSearchEntityDescriptors;
+
+ private SuggestionEntityLookup() {
+ suggestionSearchEntityOxmModel = new LinkedHashMap>();
+ suggestionSearchEntityDescriptors = new HashMap();
+ }
+
+ public synchronized static SuggestionEntityLookup getInstance() {
+
+ /*
+ * I hate this method and I want it to go away. The singleton pattern is transitory, I want this
+ * class to be wired via a bean reference instead. But from the starting point, it would require
+ * fixing all the classes across the code base up front and I don't want this task to expand
+ * beyond just refactoring the OxmModelLoader. For now I'll keep the singleton pattern, but I
+ * really want to get rid of it once we are properly spring wired.
+ */
+
+ if (instance == null) {
+ instance = new SuggestionEntityLookup();
+ }
+
+ return instance;
+ }
+
+
+ @Override
+ public void processOxmModel(DynamicJAXBContext jaxbContext) {
+
+ @SuppressWarnings("rawtypes")
+ List descriptorsList = jaxbContext.getXMLContext().getDescriptors();
+
+ for (@SuppressWarnings("rawtypes")
+ Descriptor desc : descriptorsList) {
+
+ DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
+
+ LinkedHashMap oxmProperties = new LinkedHashMap();
+
+ // Not all fields have key attributes
+ if (desc.getPrimaryKeyFields() != null) {
+ oxmProperties.put("primaryKeyAttributeNames", desc.getPrimaryKeyFields().toString()
+ .replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""));
+ }
+
+ String entityName = desc.getDefaultRootElement();
+
+ // add entityName
+ oxmProperties.put("entityName", entityName);
+
+ Map properties = entity.getDescriptor().getProperties();
+ if (properties != null) {
+ for (Map.Entry entry : properties.entrySet()) {
+
+
+ if (entry.getKey().equalsIgnoreCase("containsSuggestibleProps")) {
+
+ oxmProperties.put("containsSuggestibleProps", "true");
+
+ Vector descriptorMaps = entity.getDescriptor().getMappings();
+ List listOfSuggestableAttributes = new ArrayList();
+
+ for (DatabaseMapping descMap : descriptorMaps) {
+ if (descMap.isAbstractDirectMapping()) {
+
+ if (descMap.getProperties().get("suggestibleOnSearch") != null) {
+ String suggestableOnSearchString =
+ String.valueOf(descMap.getProperties().get("suggestibleOnSearch"));
+
+ boolean isSuggestibleOnSearch = Boolean.valueOf(suggestableOnSearchString);
+
+ if (isSuggestibleOnSearch) {
+ /* Grab attribute types for suggestion */
+ String attributeName =
+ descMap.getField().getName().replaceAll("/text\\(\\)", "");
+ listOfSuggestableAttributes.add(attributeName);
+
+ if (descMap.getProperties().get("suggestionVerbs") != null) {
+ String suggestionVerbsString =
+ String.valueOf(descMap.getProperties().get("suggestionVerbs"));
+
+ oxmProperties.put("suggestionVerbs", suggestionVerbsString);
+ }
+ }
+ }
+ }
+ }
+
+ if (!listOfSuggestableAttributes.isEmpty()) {
+ oxmProperties.put("suggestibleAttributes",
+ String.join(",", listOfSuggestableAttributes));
+ }
+ } else if (entry.getKey().equalsIgnoreCase("suggestionAliases")) {
+ oxmProperties.put("suggestionAliases", entry.getValue());
+ }
+ }
+ }
+
+ if (oxmProperties.containsKey("containsSuggestibleProps")) {
+ suggestionSearchEntityOxmModel.put(entityName, oxmProperties);
+ }
+ }
+
+ for (Entry> suggestionEntityModel : suggestionSearchEntityOxmModel
+ .entrySet()) {
+ HashMap attribute = suggestionEntityModel.getValue();
+
+ String entityName = attribute.get("entityName");
+ SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity(this);
+ suggestionSearchEntity.setEntityType(entityName);
+
+ if (attribute.get("suggestionAliases") != null) {
+ suggestionSearchEntity
+ .setSuggestionAliases(Arrays.asList(attribute.get("suggestionAliases").split(",")));
+ }
+
+ if (attribute.get("suggestibleAttributes") != null) {
+ suggestionSearchEntity.setSuggestionPropertyTypes(
+ Arrays.asList(attribute.get("suggestibleAttributes").split(",")));
+ }
+
+ SuggestionEntityDescriptor entity = new SuggestionEntityDescriptor();
+ entity.setSuggestionSearchEntity(suggestionSearchEntity);
+ entity.setEntityName(entityName);
+
+ if (attribute.get("primaryKeyAttributeNames") != null) {
+ entity.setPrimaryKeyAttributeNames(
+ Arrays.asList(attribute.get("primaryKeyAttributeNames").replace(" ", "").split(",")));
+ }
+
+ suggestionSearchEntityDescriptors.put(entityName, entity);
+ }
+ }
+
+ public Map> getSuggestionSearchEntityOxmModel() {
+ return suggestionSearchEntityOxmModel;
+ }
+
+ public void setSuggestionSearchEntityOxmModel(
+ Map> suggestionSearchEntityOxmModel) {
+ this.suggestionSearchEntityOxmModel = suggestionSearchEntityOxmModel;
+ }
+
+ public Map getSuggestionSearchEntityDescriptors() {
+ return suggestionSearchEntityDescriptors;
+ }
+
+ public void setSuggestionSearchEntityDescriptors(
+ Map suggestionSearchEntityDescriptors) {
+ this.suggestionSearchEntityDescriptors = suggestionSearchEntityDescriptors;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizer.java b/src/main/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizer.java
new file mode 100644
index 0000000..39ee8c5
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/crossentityreference/sync/CrossEntityReferenceSynchronizer.java
@@ -0,0 +1,949 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.crossentityreference.sync;
+
+import static java.util.concurrent.CompletableFuture.supplyAsync;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Supplier;
+
+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.CrossEntityReference;
+import org.onap.aai.sparky.config.oxm.CrossEntityReferenceDescriptor;
+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.SearchableEntityLookup;
+import org.onap.aai.sparky.config.oxm.SearchableOxmEntityDescriptor;
+import org.onap.aai.sparky.dal.NetworkTransaction;
+import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
+import org.onap.aai.sparky.dal.elasticsearch.config.ElasticSearchConfig;
+import org.onap.aai.sparky.dal.rest.HttpMethod;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.sync.AbstractEntitySynchronizer;
+import org.onap.aai.sparky.sync.IndexSynchronizer;
+import org.onap.aai.sparky.sync.SynchronizerConstants;
+import org.onap.aai.sparky.sync.config.ElasticSearchSchemaConfig;
+import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
+import org.onap.aai.sparky.sync.entity.IndexableCrossEntityReference;
+import org.onap.aai.sparky.sync.entity.MergableEntity;
+import org.onap.aai.sparky.sync.entity.SelfLinkDescriptor;
+import org.onap.aai.sparky.sync.enumeration.OperationState;
+import org.onap.aai.sparky.sync.enumeration.SynchronizerState;
+import org.onap.aai.sparky.sync.task.PerformActiveInventoryRetrieval;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchPut;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchRetrieval;
+import org.onap.aai.sparky.sync.task.PerformElasticSearchUpdate;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * The Class CrossEntityReferenceSynchronizer.
+ */
+public class CrossEntityReferenceSynchronizer extends AbstractEntitySynchronizer
+ implements IndexSynchronizer {
+
+ /**
+ * The Class RetryCrossEntitySyncContainer.
+ */
+ private class RetryCrossEntitySyncContainer {
+ NetworkTransaction txn;
+ IndexableCrossEntityReference icer;
+
+ /**
+ * Instantiates a new retry cross entity sync container.
+ *
+ * @param txn the txn
+ * @param icer the icer
+ */
+ public RetryCrossEntitySyncContainer(NetworkTransaction txn,
+ IndexableCrossEntityReference icer) {
+ this.txn = txn;
+ this.icer = icer;
+ }
+
+ public NetworkTransaction getNetworkTransaction() {
+ return txn;
+ }
+
+ public IndexableCrossEntityReference getIndexableCrossEntityReference() {
+ return icer;
+ }
+ }
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(CrossEntityReferenceSynchronizer.class);
+
+ private static final String SERVICE_INSTANCE = "service-instance";
+
+ private Deque selflinks;
+ private Deque retryQueue;
+ private Map retryLimitTracker;
+ private boolean isAllWorkEnumerated;
+ protected ExecutorService esPutExecutor;
+
+
+ /**
+ * Instantiates a new cross entity reference synchronizer.
+ *
+ * @param indexName the index name
+ * @throws Exception the exception
+ */
+ public CrossEntityReferenceSynchronizer(ElasticSearchSchemaConfig schemaConfig,
+ int internalSyncWorkers, int aaiWorkers, int esWorkers, NetworkStatisticsConfig aaiStatConfig,
+ NetworkStatisticsConfig esStatConfig) throws Exception {
+ super(LOG, "CERS", internalSyncWorkers, aaiWorkers, esWorkers, schemaConfig.getIndexName(),
+ aaiStatConfig, esStatConfig);
+ this.selflinks = new ConcurrentLinkedDeque();
+ this.retryQueue = new ConcurrentLinkedDeque();
+ this.retryLimitTracker = new ConcurrentHashMap();
+ this.synchronizerName = "Cross Reference Entity Synchronizer";
+ this.isAllWorkEnumerated = false;
+ this.esPutExecutor = NodeUtils.createNamedExecutor("CERS-ES-PUT", 5, LOG);
+ this.aaiEntityStats.intializeEntityCounters(
+ CrossEntityReferenceLookup.getInstance().getCrossReferenceEntityDescriptors().keySet());
+
+ this.esEntityStats.intializeEntityCounters(
+ CrossEntityReferenceLookup.getInstance().getCrossReferenceEntityDescriptors().keySet());
+ this.syncDurationInMs = -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#doSync()
+ */
+ @Override
+ public OperationState doSync() {
+ this.syncDurationInMs = -1;
+ String txnID = NodeUtils.getRandomTxnId();
+ MdcContext.initialize(txnID, "CrossEntitySynchronizer", "", "Sync", "");
+
+ resetCounters();
+ syncStartedTimeStampInMs = System.currentTimeMillis();
+ launchSyncFlow();
+ return OperationState.OK;
+ }
+
+ @Override
+ public SynchronizerState getState() {
+ if (!isSyncDone()) {
+ return SynchronizerState.PERFORMING_SYNCHRONIZATION;
+ }
+
+ return SynchronizerState.IDLE;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#getStatReport(boolean)
+ */
+ @Override
+ public String getStatReport(boolean showFinalReport) {
+ syncDurationInMs = System.currentTimeMillis() - syncStartedTimeStampInMs;
+ return getStatReport(syncDurationInMs, showFinalReport);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.sparky.synchronizer.IndexSynchronizer#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ this.shutdownExecutors();
+ }
+
+ @Override
+ protected boolean isSyncDone() {
+ int totalWorkOnHand = aaiWorkOnHand.get() + esWorkOnHand.get();
+
+ if (totalWorkOnHand > 0 || !isAllWorkEnumerated) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Launch sync flow.
+ *
+ * @return the operation state
+ */
+ private OperationState launchSyncFlow() {
+ final Map contextMap = MDC.getCopyOfContextMap();
+ Map descriptorMap =
+ CrossEntityReferenceLookup.getInstance().getCrossReferenceEntityDescriptors();
+
+ if (descriptorMap.isEmpty()) {
+ LOG.error(AaiUiMsgs.ERROR_LOADING_OXM);
+
+ return OperationState.ERROR;
+ }
+
+ Collection syncTypes = descriptorMap.keySet();
+
+ try {
+
+ /*
+ * launch a parallel async thread to process the documents for each entity-type (to max the of
+ * the configured executor anyway)
+ */
+
+ aaiWorkOnHand.set(syncTypes.size());
+
+ for (String key : syncTypes) {
+
+ supplyAsync(new Supplier() {
+
+ @Override
+ public Void get() {
+ MDC.setContextMap(contextMap);
+ OperationResult typeLinksResult = null;
+ try {
+ typeLinksResult = aaiAdapter.getSelfLinksByEntityType(key);
+ aaiWorkOnHand.decrementAndGet();
+ processEntityTypeSelfLinks(typeLinksResult);
+ } catch (Exception exc) {
+ // TODO -> LOG, what should be logged here?
+ }
+
+ return null;
+ }
+
+ }, aaiExecutor).whenComplete((result, error) -> {
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ERROR_GETTING_DATA_FROM_AAI, error.getMessage());
+ }
+ });
+ }
+
+ while (aaiWorkOnHand.get() != 0) {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(AaiUiMsgs.WAIT_FOR_ALL_SELFLINKS_TO_BE_COLLECTED);
+ }
+
+ Thread.sleep(1000);
+ }
+
+ aaiWorkOnHand.set(selflinks.size());
+ isAllWorkEnumerated = true;
+ performSync();
+
+ while (!isSyncDone()) {
+ performRetrySync();
+ Thread.sleep(1000);
+ }
+
+ /*
+ * Make sure we don't hang on to retries that failed which could cause issues during future
+ * syncs
+ */
+ retryLimitTracker.clear();
+
+ } catch (Exception exc) {
+ // TODO -> LOG, waht should be logged here?
+ }
+
+ return OperationState.OK;
+ }
+
+ /**
+ * Perform sync.
+ */
+ private void performSync() {
+ while (selflinks.peek() != null) {
+
+ SelfLinkDescriptor linkDescriptor = selflinks.poll();
+ aaiWorkOnHand.decrementAndGet();
+
+ CrossEntityReferenceDescriptor descriptor = null;
+
+ if (linkDescriptor.getSelfLink() != null && linkDescriptor.getEntityType() != null) {
+
+ descriptor = CrossEntityReferenceLookup.getInstance().getCrossReferenceEntityDescriptors()
+ .get(linkDescriptor.getEntityType());
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, linkDescriptor.getEntityType());
+ // go to next element in iterator
+ continue;
+ }
+
+ if (descriptor.hasCrossEntityReferences()) {
+
+ NetworkTransaction txn = new NetworkTransaction();
+ txn.setDescriptor(descriptor);
+ txn.setLink(linkDescriptor.getSelfLink());
+ txn.setQueryParameters(linkDescriptor.getDepthModifier());
+ txn.setOperationType(HttpMethod.GET);
+ txn.setEntityType(linkDescriptor.getEntityType());
+
+ aaiWorkOnHand.incrementAndGet();
+
+ supplyAsync(new PerformActiveInventoryRetrieval(txn, aaiAdapter), aaiExecutor)
+ .whenComplete((result, error) -> {
+
+ aaiWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.SELF_LINK_GET, error.getLocalizedMessage());
+ } else {
+ if (result == null) {
+ LOG.error(AaiUiMsgs.SELF_LINK_CROSS_REF_SYNC);
+ } else {
+ updateActiveInventoryCounters(result);
+ fetchDocumentForUpsert(result);
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+
+ /**
+ * Process entity type self links.
+ *
+ * @param operationResult the operation result
+ */
+ private void processEntityTypeSelfLinks(OperationResult operationResult) {
+
+ JsonNode rootNode = null;
+
+ final String jsonResult = operationResult.getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0) {
+
+ try {
+ rootNode = mapper.readTree(jsonResult);
+ } catch (IOException exc) {
+ // TODO // TODO -> LOG, waht should be logged here?
+ }
+
+ JsonNode resultData = rootNode.get("result-data");
+ ArrayNode resultDataArrayNode = null;
+
+ CrossEntityReferenceLookup cerLookup = CrossEntityReferenceLookup.getInstance();
+
+ if (resultData.isArray()) {
+ resultDataArrayNode = (ArrayNode) resultData;
+
+ Iterator elementIterator = resultDataArrayNode.elements();
+ JsonNode element = null;
+
+ while (elementIterator.hasNext()) {
+ element = elementIterator.next();
+
+ final String resourceType = NodeUtils.getNodeFieldAsText(element, "resource-type");
+ final String resourceLink = NodeUtils.getNodeFieldAsText(element, "resource-link");
+
+ CrossEntityReferenceDescriptor descriptor = null;
+
+ if (resourceType != null && resourceLink != null) {
+ descriptor = cerLookup.getCrossReferenceEntityDescriptors().get(resourceType);
+
+ if (descriptor == null) {
+ LOG.error(AaiUiMsgs.MISSING_ENTITY_DESCRIPTOR, resourceType);
+ // go to next element in iterator
+ continue;
+ }
+ if (descriptor.hasCrossEntityReferences()) {
+ selflinks.add(new SelfLinkDescriptor(resourceLink,
+ SynchronizerConstants.DEPTH_ALL_MODIFIER, resourceType));
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * By providing the entity type and a json node for the entity, determine the primary key name(s)
+ * + primary key value(s) sufficient to build an entity query string of the following format:
+ *
+ * .:
+ *
+ * @return - a composite string in the above format or null
+ */
+ private String determineEntityQueryString(String entityType, JsonNode entityJsonNode) {
+
+ OxmEntityDescriptor entityDescriptor =
+ OxmEntityLookup.getInstance().getEntityDescriptors().get(entityType);
+
+ String queryString = null;
+
+ if (entityDescriptor != null) {
+
+ final List primaryKeyNames = entityDescriptor.getPrimaryKeyAttributeNames();
+ final List keyValues = new ArrayList();
+ NodeUtils.extractFieldValuesFromObject(entityJsonNode, primaryKeyNames, keyValues);
+
+ queryString = entityType + "." + NodeUtils.concatArray(primaryKeyNames, "/") + ":"
+ + NodeUtils.concatArray(keyValues);
+
+ }
+
+ return queryString;
+
+
+ }
+
+ /**
+ * Fetch document for upsert.
+ *
+ * @param txn the txn
+ */
+ private void fetchDocumentForUpsert(NetworkTransaction txn) {
+
+ if (!txn.getOperationResult().wasSuccessful()) {
+ LOG.error(AaiUiMsgs.SELF_LINK_GET, txn.getOperationResult().getResult());
+ return;
+ }
+
+ CrossEntityReferenceDescriptor cerDescriptor = CrossEntityReferenceLookup.getInstance()
+ .getCrossReferenceEntityDescriptors().get(txn.getDescriptor().getEntityName());
+
+ if (cerDescriptor != null && cerDescriptor.hasCrossEntityReferences()) {
+
+ final String jsonResult = txn.getOperationResult().getResult();
+
+ if (jsonResult != null && jsonResult.length() > 0) {
+
+ /**
+ * Here's what we are going to do:
+ *
+ * Extract primary key name and value from the parent type.
+ * Extract the primary key and value from the nested child instance.
+ * Build a generic query to discover the self-link for the nested-child-instance using
+ * parent and child.
+ * Set the self-link on the child.
+ * Generate the id that will allow the elastic-search upsert to work.
+ * Rinse and repeat.
+ */
+
+ CrossEntityReference cerDefinition = cerDescriptor.getCrossEntityReference();
+
+ if (cerDefinition != null) {
+ JsonNode convertedNode = null;
+ try {
+ convertedNode =
+ NodeUtils.convertJsonStrToJsonNode(txn.getOperationResult().getResult());
+
+ final String parentEntityQueryString =
+ determineEntityQueryString(txn.getEntityType(), convertedNode);
+
+ List extractedParentEntityAttributeValues = new ArrayList();
+
+ NodeUtils.extractFieldValuesFromObject(convertedNode,
+ cerDefinition.getReferenceAttributes(), extractedParentEntityAttributeValues);
+
+ List nestedTargetEntityInstances = new ArrayList();
+ NodeUtils.extractObjectsByKey(convertedNode, cerDefinition.getTargetEntityType(),
+ nestedTargetEntityInstances);
+
+ for (JsonNode targetEntityInstance : nestedTargetEntityInstances) {
+
+ if (cerDescriptor != null) {
+
+ String childEntityType = cerDefinition.getTargetEntityType();
+
+ List childPrimaryKeyNames = cerDescriptor.getPrimaryKeyAttributeNames();
+
+ List childKeyValues = new ArrayList();
+ NodeUtils.extractFieldValuesFromObject(targetEntityInstance, childPrimaryKeyNames,
+ childKeyValues);
+
+ String childEntityQueryKeyString =
+ childEntityType + "." + NodeUtils.concatArray(childPrimaryKeyNames, "/") + ":"
+ + NodeUtils.concatArray(childKeyValues);
+
+ /**
+ * Build generic-query to query child instance self-link from AAI
+ */
+ List orderedQueryKeyParams = new ArrayList();
+
+ /**
+ * At present, there is an issue with resolving the self-link using the
+ * generic-query with nothing more than the service-instance identifier and the
+ * service-subscription. There is another level of detail we don't have access to
+ * unless we parse it out of the service-subscription self-link, which is a coupling
+ * I would like to avoid. Fortunately, there is a workaround, but only for
+ * service-instances, which is presently our only use-case for the
+ * cross-entity-reference in R1707. Going forwards hopefully there will be other
+ * ways to resolve a child self-link using parental embedded meta data that we don't
+ * currently have.
+ *
+ * The work-around with the service-instance entity-type is that it's possible to
+ * request the self-link using only the service-instance-id because of a historical
+ * AAI functional query requirement that it be possible to query a service-instance
+ * only by it's service-instance-id. This entity type is the only one in the system
+ * that can be queried this way which makes it a very limited workaround, but good
+ * enough for the current release.
+ */
+
+ if (SERVICE_INSTANCE.equals(childEntityType)) {
+ orderedQueryKeyParams.clear();
+ orderedQueryKeyParams.add(childEntityQueryKeyString);
+ } else {
+ orderedQueryKeyParams.add(parentEntityQueryString);
+ orderedQueryKeyParams.add(childEntityQueryKeyString);
+ }
+
+ String genericQueryStr = null;
+ try {
+ genericQueryStr =
+ aaiAdapter.getGenericQueryForSelfLink(childEntityType, orderedQueryKeyParams);
+
+ if (genericQueryStr != null) {
+ aaiWorkOnHand.incrementAndGet();
+
+ OperationResult aaiQueryResult = aaiAdapter.queryActiveInventoryWithRetries(
+ genericQueryStr, "application/json", aaiAdapter.getNumRequestRetries());
+
+ aaiWorkOnHand.decrementAndGet();
+
+ if (aaiQueryResult != null && aaiQueryResult.wasSuccessful()) {
+
+ Collection entityLinks = new ArrayList();
+ JsonNode genericQueryResult = null;
+ try {
+ genericQueryResult =
+ NodeUtils.convertJsonStrToJsonNode(aaiQueryResult.getResult());
+
+ if (genericQueryResult != null) {
+
+ NodeUtils.extractObjectsByKey(genericQueryResult, "resource-link",
+ entityLinks);
+
+ String selfLink = null;
+
+ if (entityLinks.size() != 1) {
+ /**
+ * an ambiguity exists where we can't reliably determine the self 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();
+
+ SearchableEntityLookup searchableEntityLookup =
+ SearchableEntityLookup.getInstance();
+
+ 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(ActiveInventoryConfig.extractResourcePath(selfLink));
+
+ icer.deriveFields();
+
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + icer.getId(), getIndexName());
+ } 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);
+ }
+
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.JSON_CONVERSION_ERROR, JsonNode.class.toString(),
+ exc.getLocalizedMessage());
+ }
+
+ } else {
+ String message = "Entity sync failed because AAI query failed with error "
+ + aaiQueryResult.getResult();
+ LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_QUERY_ERROR, message);
+ }
+
+ } else {
+ String message =
+ "Entity Sync failed because generic query str could not be determined.";
+ LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_QUERY_ERROR, message);
+ }
+ } catch (Exception exc) {
+ String message =
+ "Failed to sync entity because generation of generic query failed with error = "
+ + exc.getMessage();
+ LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_QUERY_ERROR, message);
+ }
+
+ }
+ }
+
+ } catch (IOException ioe) {
+ LOG.error(AaiUiMsgs.JSON_PROCESSING_ERROR, ioe.getMessage());
+ }
+ }
+
+ }
+
+ } else {
+ LOG.error(AaiUiMsgs.ENTITY_SYNC_FAILED_DESCRIPTOR_NOT_FOUND, txn.getEntityType());
+ }
+ }
+
+ /**
+ * Perform document upsert.
+ *
+ * @param esGetResult the es get result
+ * @param icer the icer
+ */
+ protected void performDocumentUpsert(NetworkTransaction esGetResult,
+ IndexableCrossEntityReference icer) {
+ /**
+ *
+ *
+ * As part of the response processing we need to do the following:
+ * - 1. Extract the version (if present), it will be the ETAG when we use the
+ * Search-Abstraction-Service
+ *
- 2. Spawn next task which is to do the PUT operation into elastic with or with the version
+ * tag
+ *
- a) if version is null or RC=404, then standard put, no _update with version tag
+ *
- b) if version != null, do PUT with _update?version= (versionNumber) in the URI to elastic
+ *
+ *
+ */
+ String link = null;
+ try {
+ link = getElasticFullUrl("/" + icer.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_LINK_UPSERT, exc.getLocalizedMessage());
+ return;
+ }
+
+ boolean wasEntryDiscovered = false;
+ String versionNumber = null;
+ if (esGetResult.getOperationResult().getResultCode() == 404) {
+ LOG.info(AaiUiMsgs.ES_SIMPLE_PUT, icer.getEntityPrimaryKeyValue());
+ } else if (esGetResult.getOperationResult().getResultCode() == 200) {
+ wasEntryDiscovered = true;
+ try {
+ versionNumber = NodeUtils.extractFieldValueFromObject(
+ NodeUtils.convertJsonStrToJsonNode(esGetResult.getOperationResult().getResult()),
+ "_version");
+ } catch (IOException exc) {
+ LOG.error(AaiUiMsgs.ES_ABORT_CROSS_ENTITY_REF_SYNC, "version Number",
+ icer.getEntityPrimaryKeyValue(), exc.getLocalizedMessage());
+ return;
+ }
+ } else {
+ /*
+ * Not being a 200 does not mean a failure. eg 201 is returned for created. TODO -> Should we
+ * return.
+ */
+ LOG.info(AaiUiMsgs.ES_OPERATION_RETURN_CODE,
+ String.valueOf(esGetResult.getOperationResult().getResultCode()));
+ return;
+ }
+
+ try {
+ String jsonPayload = null;
+ if (wasEntryDiscovered) {
+ try {
+ ArrayList sourceObject = new ArrayList();
+ NodeUtils.extractObjectsByKey(
+ NodeUtils.convertJsonStrToJsonNode(esGetResult.getOperationResult().getResult()),
+ "_source", sourceObject);
+
+ if (!sourceObject.isEmpty()) {
+ String responseSource = NodeUtils.convertObjectToJson(sourceObject.get(0), false);
+ MergableEntity me = mapper.readValue(responseSource, MergableEntity.class);
+ ObjectReader updater = mapper.readerForUpdating(me);
+ MergableEntity merged = updater.readValue(icer.getAsJson());
+ jsonPayload = mapper.writeValueAsString(merged);
+ }
+ } catch (IOException exc) {
+ LOG.error(AaiUiMsgs.ES_ABORT_CROSS_ENTITY_REF_SYNC, "source value",
+ icer.getEntityPrimaryKeyValue(), exc.getLocalizedMessage());
+ return;
+ }
+ } else {
+ jsonPayload = icer.getAsJson();
+ }
+
+ if (wasEntryDiscovered) {
+ if (versionNumber != null && jsonPayload != null) {
+
+ String requestPayload = elasticSearchAdapter.buildBulkImportOperationRequest(
+ getIndexName(), ElasticSearchConfig.getConfig().getType(), icer.getId(),
+ versionNumber, jsonPayload);
+
+ NetworkTransaction transactionTracker = new NetworkTransaction();
+ transactionTracker.setEntityType(esGetResult.getEntityType());
+ transactionTracker.setDescriptor(esGetResult.getDescriptor());
+ transactionTracker.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ supplyAsync(new PerformElasticSearchUpdate(ElasticSearchConfig.getConfig().getBulkUrl(),
+ requestPayload, elasticSearchAdapter, transactionTracker), esPutExecutor)
+ .whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ES_CROSS_ENTITY_REF_PUT, error.getLocalizedMessage());
+ } else {
+ updateElasticSearchCounters(result);
+ processStoreDocumentResult(result, esGetResult, icer);
+ }
+ });
+ }
+
+ } else {
+ if (link != null && jsonPayload != null) {
+
+ NetworkTransaction updateElasticTxn = new NetworkTransaction();
+ updateElasticTxn.setLink(link);
+ updateElasticTxn.setEntityType(esGetResult.getEntityType());
+ updateElasticTxn.setDescriptor(esGetResult.getDescriptor());
+ updateElasticTxn.setOperationType(HttpMethod.PUT);
+
+ esWorkOnHand.incrementAndGet();
+ supplyAsync(
+ new PerformElasticSearchPut(jsonPayload, updateElasticTxn, elasticSearchAdapter),
+ esPutExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ES_CROSS_ENTITY_REF_PUT, error.getLocalizedMessage());
+ } else {
+ updateElasticSearchCounters(result);
+ processStoreDocumentResult(result, esGetResult, icer);
+ }
+ });
+ }
+ }
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_CROSS_ENTITY_REF_PUT, exc.getLocalizedMessage());
+ }
+ }
+
+ /**
+ * Process store document result.
+ *
+ * @param esPutResult the es put result
+ * @param esGetResult the es get result
+ * @param icer the icer
+ */
+ private void processStoreDocumentResult(NetworkTransaction esPutResult,
+ NetworkTransaction esGetResult, IndexableCrossEntityReference icer) {
+
+ OperationResult or = esPutResult.getOperationResult();
+
+ if (!or.wasSuccessful()) {
+ if (or.getResultCode() == VERSION_CONFLICT_EXCEPTION_CODE) {
+
+ if (shouldAllowRetry(icer.getId())) {
+
+ esWorkOnHand.incrementAndGet();
+
+ RetryCrossEntitySyncContainer rsc = new RetryCrossEntitySyncContainer(esGetResult, icer);
+ retryQueue.push(rsc);
+
+ LOG.warn(AaiUiMsgs.ES_CROSS_REF_SYNC_VERSION_CONFLICT);
+ }
+ } else {
+ LOG.error(AaiUiMsgs.ES_CROSS_REF_SYNC_FAILURE, String.valueOf(or.getResultCode()),
+ or.getResult());
+ }
+ }
+ }
+
+ /**
+ * Perform retry sync.
+ */
+ private void performRetrySync() {
+ while (retryQueue.peek() != null) {
+
+ RetryCrossEntitySyncContainer rsc = retryQueue.poll();
+ if (rsc != null) {
+
+ IndexableCrossEntityReference icer = rsc.getIndexableCrossEntityReference();
+ NetworkTransaction txn = rsc.getNetworkTransaction();
+
+ String link = null;
+ try {
+ // In this retry flow the icer object has already
+ // derived its fields
+ link = getElasticFullUrl("/" + icer.getId(), getIndexName());
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.ES_FAILED_TO_CONSTRUCT_URI, exc.getLocalizedMessage());
+ }
+
+ if (link != null) {
+ NetworkTransaction retryTransaction = new NetworkTransaction();
+ retryTransaction.setLink(link);
+ retryTransaction.setEntityType(txn.getEntityType());
+ retryTransaction.setDescriptor(txn.getDescriptor());
+ retryTransaction.setOperationType(HttpMethod.GET);
+
+ /*
+ * IMPORTANT - DO NOT incrementAndGet the esWorkOnHand as this is a retry flow and we did
+ * that for this request already when queuing the failed PUT!
+ */
+
+ supplyAsync(new PerformElasticSearchRetrieval(retryTransaction, elasticSearchAdapter),
+ esExecutor).whenComplete((result, error) -> {
+
+ esWorkOnHand.decrementAndGet();
+
+ if (error != null) {
+ LOG.error(AaiUiMsgs.ES_RETRIEVAL_FAILED_RESYNC, error.getLocalizedMessage());
+ } else {
+ updateElasticSearchCounters(result);
+ performDocumentUpsert(result, icer);
+ }
+ });
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Should allow retry.
+ *
+ * @param id the id
+ * @return true, if successful
+ */
+ private boolean shouldAllowRetry(String id) {
+ boolean isRetryAllowed = true;
+ if (retryLimitTracker.get(id) != null) {
+ Integer currentCount = retryLimitTracker.get(id);
+ if (currentCount.intValue() >= RETRY_COUNT_PER_ENTITY_LIMIT.intValue()) {
+ isRetryAllowed = false;
+ LOG.error(AaiUiMsgs.ES_CROSS_ENTITY_RESYNC_LIMIT, id);
+ } else {
+ Integer newCount = new Integer(currentCount.intValue() + 1);
+ retryLimitTracker.put(id, newCount);
+ }
+
+ } else {
+ Integer firstRetryCount = new Integer(1);
+ retryLimitTracker.put(id, firstRetryCount);
+ }
+
+ return isRetryAllowed;
+ }
+
+ /**
+ * Gets the populated document.
+ *
+ * @param entityNode the entity node
+ * @param resultDescriptor the result descriptor
+ * @return the populated document
+ * @throws JsonProcessingException the json processing exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ protected IndexableCrossEntityReference getPopulatedDocument(JsonNode entityNode,
+ OxmEntityDescriptor resultDescriptor) throws JsonProcessingException, IOException {
+
+ IndexableCrossEntityReference icer = new IndexableCrossEntityReference();
+
+ icer.setEntityType(resultDescriptor.getEntityName());
+
+ List primaryKeyValues = new ArrayList();
+ String pkeyValue = null;
+
+ for (String keyName : resultDescriptor.getPrimaryKeyAttributeNames()) {
+ pkeyValue = NodeUtils.getNodeFieldAsText(entityNode, keyName);
+ if (pkeyValue != null) {
+ primaryKeyValues.add(pkeyValue);
+ } else {
+ LOG.warn(AaiUiMsgs.ES_PKEYVALUE_NULL, resultDescriptor.getEntityName());
+ }
+ }
+
+ final String primaryCompositeKeyValue = NodeUtils.concatArray(primaryKeyValues, "/");
+ icer.setEntityPrimaryKeyValue(primaryCompositeKeyValue);
+
+ return icer;
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/sparky/dal/ActiveInventoryAdapter.java b/src/main/java/org/onap/aai/sparky/dal/ActiveInventoryAdapter.java
new file mode 100644
index 0000000..40bb98c
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/dal/ActiveInventoryAdapter.java
@@ -0,0 +1,460 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.dal;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URIBuilder;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.restclient.client.RestClient;
+import org.onap.aai.restclient.enums.RestAuthenticationMode;
+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.dal.exception.ElasticSearchOperationException;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.util.Encryptor;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
+
+
+
+/**
+ * The Class ActiveInventoryAdapter.
+ */
+
+public class ActiveInventoryAdapter {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(ActiveInventoryAdapter.class);
+
+ private static final String HEADER_TRANS_ID = "X-TransactionId";
+ private static final String HEADER_FROM_APP_ID = "X-FromAppId";
+ private static final String HEADER_AUTHORIZATION = "Authorization";
+
+ private static final String HTTP_SCHEME = "http";
+ private static final String HTTPS_SCHEME = "https";
+
+ private static final String TRANSACTION_ID_PREFIX = "txnId-";
+ private static final String UI_APP_NAME = "AAI-UI";
+
+ private OxmModelLoader oxmModelLoader;
+ private OxmEntityLookup oxmEntityLookup;
+
+ private RestClient restClient;
+
+ private String activeInventoryIpAddress;
+ private String activeInventoryServerPort;
+ private int numRequestRetries;
+ private String basicAuthUserName;
+ private String basicAuthPassword;
+ private RestAuthenticationMode restAuthenticationMode;
+ private int connectTimeoutInMs;
+ private int readTimeoutInMs;
+
+ /**
+ * Instantiates a new active inventory adapter.
+ *
+ */
+
+ public ActiveInventoryAdapter(OxmModelLoader oxmModelLoader,
+ RestAuthenticationMode authenticationMode, boolean validateServerHostname,
+ boolean validateServerCertChain, String certFileName, String certPassword,
+ String truststoreFileName, int connectTimeoutInMs, int readTimeoutInMs)
+ throws ElasticSearchOperationException, IOException {
+
+ this.oxmModelLoader = oxmModelLoader;
+ this.restAuthenticationMode = authenticationMode;
+ this.connectTimeoutInMs = connectTimeoutInMs;
+ this.readTimeoutInMs = readTimeoutInMs;
+
+
+ Encryptor enc = new Encryptor();
+ String certFileNameFullPath = TierSupportUiConstants.CONFIG_AUTH_LOCATION + certFileName;
+ String decryptedCertPassword = enc.decryptValue(certPassword);
+ String truststoreFileNameFullPath =
+ TierSupportUiConstants.CONFIG_AUTH_LOCATION + truststoreFileName;
+
+ this.restClient = new RestClient().authenticationMode(authenticationMode)
+ .validateServerCertChain(validateServerCertChain)
+ .validateServerHostname(validateServerHostname).clientCertFile(certFileNameFullPath)
+ .clientCertPassword(decryptedCertPassword).trustStore(truststoreFileNameFullPath)
+ .connectTimeoutMs(connectTimeoutInMs).readTimeoutMs(readTimeoutInMs);
+
+ }
+
+ public ActiveInventoryAdapter(OxmModelLoader oxmModelLoader,
+ RestAuthenticationMode authenticationMode, boolean validateServerHostname,
+ boolean validateServerCertChain, String basicAuthUserName, String basicAuthPassword,
+ int connectTimeoutInMs, int readTimeoutInMs)
+ throws ElasticSearchOperationException, IOException {
+
+ this.oxmModelLoader = oxmModelLoader;
+ this.restAuthenticationMode = authenticationMode;
+
+ this.restClient = new RestClient().authenticationMode(authenticationMode)
+ .validateServerCertChain(validateServerCertChain)
+ .validateServerHostname(validateServerHostname).connectTimeoutMs(connectTimeoutInMs)
+ .readTimeoutMs(readTimeoutInMs);
+
+ this.basicAuthUserName = basicAuthUserName;
+ this.basicAuthPassword = basicAuthPassword;
+
+ }
+
+
+ protected Map> getMessageHeaders() {
+
+ Map> headers = new HashMap>();
+
+ headers.putIfAbsent(HEADER_FROM_APP_ID, new ArrayList());
+ headers.get(HEADER_FROM_APP_ID).add(UI_APP_NAME);
+
+ headers.putIfAbsent(HEADER_TRANS_ID, new ArrayList());
+ headers.get(HEADER_TRANS_ID).add(TRANSACTION_ID_PREFIX + NodeUtils.getRandomTxnId());
+
+ if (restAuthenticationMode == RestAuthenticationMode.SSL_BASIC) {
+
+ headers.putIfAbsent(HEADER_AUTHORIZATION, new ArrayList());
+ headers.get(HEADER_AUTHORIZATION).add(getBasicAuthenticationCredentials());
+
+ }
+
+ return headers;
+ }
+
+ protected String getBasicAuthenticationCredentials() {
+ String usernameAndPassword = String.join(":", basicAuthUserName, basicAuthPassword);
+ return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
+ }
+
+ public int getNumRequestRetries() {
+ return numRequestRetries;
+ }
+
+
+
+ public void setNumRequestRetries(int numRequestRetries) {
+ this.numRequestRetries = numRequestRetries;
+ }
+
+ public OxmEntityLookup getOxmEntityLookup() {
+ return oxmEntityLookup;
+ }
+
+ public void setOxmEntityLookup(OxmEntityLookup oxmEntityLookup) {
+ this.oxmEntityLookup = oxmEntityLookup;
+ }
+
+ public String getActiveInventoryIpAddress() {
+ return activeInventoryIpAddress;
+ }
+
+ public void setActiveInventoryIpAddress(String activeInventoryIpAddress) {
+ this.activeInventoryIpAddress = activeInventoryIpAddress;
+ }
+
+ public String getActiveInventoryServerPort() {
+ return activeInventoryServerPort;
+ }
+
+ public void setActiveInventoryServerPort(String activeInventoryServerPort) {
+ this.activeInventoryServerPort = activeInventoryServerPort;
+ }
+
+ protected String getResourceBasePath() {
+
+ String versionStr = null;
+ if (oxmModelLoader != null) {
+ versionStr = String.valueOf(oxmModelLoader.getLatestVersionNum());
+ }
+
+ return "/aai/v" + versionStr;
+
+ }
+
+ public int getConnectTimeoutInMs() {
+ return this.connectTimeoutInMs;
+ }
+
+ public int getReadTimeoutInMs() {
+ return this.readTimeoutInMs;
+ }
+
+ /**
+ * Gets the full url.
+ *
+ * @param resourceUrl the resource url
+ * @return the full url
+ * @throws Exception the exception
+ */
+ private String getFullUrl(String resourceUrl) throws Exception {
+ final String basePath = getResourceBasePath();
+ return String.format("https://%s:%s%s%s", activeInventoryIpAddress, activeInventoryServerPort,
+ basePath, resourceUrl);
+ }
+
+ public String getGenericQueryForSelfLink(String startNodeType, List queryParams)
+ throws Exception {
+
+ URIBuilder urlBuilder = new URIBuilder(getFullUrl("/search/generic-query"));
+
+ for (String queryParam : queryParams) {
+ urlBuilder.addParameter("key", queryParam);
+ }
+
+ urlBuilder.addParameter("start-node-type", startNodeType);
+ urlBuilder.addParameter("include", startNodeType);
+
+ final String constructedLink = urlBuilder.toString();
+
+ return constructedLink;
+
+ }
+
+
+ public OperationResult getSelfLinksByEntityType(String entityType) throws Exception {
+
+ /*
+ * For this one, I want to dynamically construct the nodes-query for self-link discovery as a
+ * utility method that will use the OXM model entity data to drive the query as well.
+ */
+
+ if (entityType == null) {
+ throw new NullPointerException(
+ "Failed to getSelfLinksByEntityType() because entityType is null");
+ }
+
+ OxmEntityDescriptor entityDescriptor = oxmEntityLookup.getEntityDescriptors().get(entityType);
+
+ if (entityDescriptor == null) {
+ throw new NoSuchElementException("Failed to getSelfLinksByEntityType() because could"
+ + " not find entity descriptor from OXM with type = " + entityType);
+ }
+
+ String link = null;
+ final String primaryKeyStr =
+ NodeUtils.concatArray(entityDescriptor.getPrimaryKeyAttributeNames(), "/");
+
+ link = getFullUrl("/search/nodes-query?search-node-type=" + entityType + "&filter="
+ + primaryKeyStr + ":EXISTS");
+
+
+ return restClient.get(link, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE);
+
+ }
+
+ public OperationResult getSelfLinkForEntity(String entityType, String primaryKeyName,
+ String primaryKeyValue) throws Exception {
+
+ if (entityType == null) {
+ throw new NullPointerException("Failed to getSelfLinkForEntity() because entityType is null");
+ }
+
+ if (primaryKeyName == null) {
+ throw new NullPointerException(
+ "Failed to getSelfLinkForEntity() because primaryKeyName is null");
+ }
+
+ if (primaryKeyValue == null) {
+ throw new NullPointerException(
+ "Failed to getSelfLinkForEntity() because primaryKeyValue is null");
+ }
+
+ /*
+ * Try to protect ourselves from illegal URI formatting exceptions caused by characters that
+ * aren't natively supported in a URI, but can be escaped to make them legal.
+ */
+
+ String encodedEntityType = URLEncoder.encode(entityType, "UTF-8");
+ String encodedPrimaryKeyName = URLEncoder.encode(primaryKeyName, "UTF-8");
+ String encodedPrimaryKeyValue = URLEncoder.encode(primaryKeyValue, "UTF-8");
+
+ String link = null;
+
+ if ("service-instance".equals(entityType)) {
+
+ link = getFullUrl("/search/generic-query?key=" + encodedEntityType + "."
+ + encodedPrimaryKeyName + ":" + encodedPrimaryKeyValue + "&start-node-type="
+ + encodedEntityType + "&include=customer&depth=2");
+
+ } else {
+
+ link =
+ getFullUrl("/search/generic-query?key=" + encodedEntityType + "." + encodedPrimaryKeyName
+ + ":" + encodedPrimaryKeyValue + "&start-node-type=" + encodedEntityType);
+
+ }
+
+ return queryActiveInventoryWithRetries(link, "application/json", numRequestRetries);
+
+ }
+
+
+ /**
+ * Our retry conditions should be very specific.
+ *
+ * @param r the r
+ * @return true, if successful
+ */
+ private boolean shouldRetryRequest(OperationResult r) {
+
+ if (r == null) {
+ return true;
+ }
+
+ int rc = r.getResultCode();
+
+ if (rc == 200) {
+ return false;
+ }
+
+ if (rc == 404) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Query active inventory.
+ *
+ * @param url the url
+ * @param acceptContentType the accept content type
+ * @return the operation result
+ */
+ // package protected for test classes instead of private
+ OperationResult queryActiveInventory(String url, String acceptContentType) {
+
+ return restClient.get(url, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE);
+
+ }
+
+ public OperationResult queryActiveInventoryWithRetries(String url, String responseType,
+ int numRetries) {
+
+ OperationResult result = null;
+
+ for (int retryCount = 0; retryCount < numRetries; retryCount++) {
+
+ LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(retryCount + 1));
+
+ result = queryActiveInventory(url, responseType);
+
+ /**
+ * Record number of times we have attempted the request to later summarize how many times we
+ * are generally retrying over thousands of messages in a sync.
+ *
+ * If the number of retries is surprisingly high, then we need to understand why that is as
+ * the number of retries is also causing a heavier load on AAI beyond the throttling controls
+ * we already have in place in term of the transaction rate controller and number of
+ * parallelized threads per task processor.
+ */
+
+ result.setNumRetries(retryCount);
+
+ if (!shouldRetryRequest(result)) {
+
+ result.setFromCache(false);
+ LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(retryCount + 1));
+
+ return result;
+ }
+
+ try {
+ /*
+ * Sleep between re-tries to be nice to the target system.
+ */
+ Thread.sleep(50);
+ } catch (InterruptedException exc) {
+ LOG.error(AaiUiMsgs.QUERY_AAI_WAIT_INTERRUPTION, exc.getLocalizedMessage());
+ break;
+ }
+ LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(retryCount + 1));
+
+ }
+
+ LOG.info(AaiUiMsgs.QUERY_AAI_RETRY_MAXED_OUT, url);
+
+ return result;
+
+ }
+
+ public String repairSelfLink(String selfLink) {
+ return repairSelfLink(selfLink, null);
+ }
+
+ /**
+ * This method adds a scheme, host and port (if missing) to the passed-in URI. If these parts of
+ * the URI are already present, they will not be duplicated.
+ *
+ * @param selflink The URI to repair
+ * @param queryParams The query parameters as a single string
+ * @return The corrected URI (i.e. includes a scheme/host/port)
+ */
+ public String repairSelfLink(String selflink, String queryParams) {
+ if (selflink == null) {
+ return selflink;
+ }
+
+ UriBuilder builder = UriBuilder.fromPath(selflink).host(activeInventoryIpAddress)
+ .port(Integer.parseInt(activeInventoryServerPort));
+
+ switch (restAuthenticationMode) {
+
+ case SSL_BASIC:
+ case SSL_CERT: {
+ builder.scheme(HTTPS_SCHEME);
+ break;
+ }
+
+ default: {
+ builder.scheme(HTTP_SCHEME);
+ }
+ }
+
+ boolean includeQueryParams = ((null != queryParams) && (!"".equals(queryParams)));
+
+ /*
+ * builder.build().toString() will encode special characters to hexadecimal pairs prefixed with
+ * a '%' so we're adding the query parameters separately, in their UTF-8 representations, so
+ * that characters such as '?', '&', etc. remain intact as needed by the synchronizer
+ */
+ return (builder.build().toString() + (includeQueryParams ? queryParams : ""));
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/dal/ElasticSearchAdapter.java b/src/main/java/org/onap/aai/sparky/dal/ElasticSearchAdapter.java
new file mode 100644
index 0000000..1e2bb8d
--- /dev/null
+++ b/src/main/java/org/onap/aai/sparky/dal/ElasticSearchAdapter.java
@@ -0,0 +1,120 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.dal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.restclient.client.RestClient;
+import org.onap.aai.restclient.enums.RestAuthenticationMode;
+
+/**
+ * The Class ElasticSearchAdapter.
+ *
+ */
+public class ElasticSearchAdapter {
+
+ private static final String BULK_IMPORT_INDEX_TEMPLATE =
+ "{\"index\":{\"_index\":\"%s\",\"_type\":\"%s\",\"_id\":\"%s\", \"_version\":\"%s\"}}\n";
+
+ private RestClient restClient;
+
+ /**
+ * Instantiates a new elastic search adapter.
+ */
+ public ElasticSearchAdapter(RestAuthenticationMode restAuthenticationMode, int connectTimeoutInMs,
+ int readTimeoutInMs) {
+
+ this.restClient = new RestClient().authenticationMode(restAuthenticationMode)
+ .connectTimeoutMs(connectTimeoutInMs).readTimeoutMs(readTimeoutInMs);
+
+ }
+
+ protected Map> getMessageHeaders() {
+ Map> headers = new HashMap>();
+ // insert mandatory headers if there are any
+ return headers;
+ }
+
+ public OperationResult doGet(String url, MediaType acceptContentType) {
+ return restClient.get(url, getMessageHeaders(), acceptContentType);
+ }
+
+ public OperationResult doDelete(String url, MediaType acceptContentType) {
+ return restClient.delete(url, getMessageHeaders(), acceptContentType);
+ }
+
+ public OperationResult doPost(String url, String jsonPayload, MediaType acceptContentType) {
+ return restClient.post(url, jsonPayload, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE,
+ acceptContentType);
+ }
+
+ public OperationResult doPut(String url, String jsonPayload, MediaType acceptContentType) {
+ return restClient.put(url, jsonPayload, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE,
+ acceptContentType);
+ }
+
+ public OperationResult doPatch(String url, String jsonPayload, MediaType acceptContentType) {
+
+ Map> headers = getMessageHeaders();
+ headers.putIfAbsent("X-HTTP-Method-Override", new ArrayList());
+ headers.get("X-HTTP-Method-Override").add("PATCH");
+
+ return restClient.post(url, jsonPayload, headers, MediaType.APPLICATION_JSON_TYPE,
+ acceptContentType);
+ }
+
+ public OperationResult doHead(String url, MediaType acceptContentType) {
+ return restClient.head(url, getMessageHeaders(), acceptContentType);
+ }
+
+ public OperationResult doBulkOperation(String url, String payload) {
+ return restClient.put(url, payload, getMessageHeaders(),
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ public String buildBulkImportOperationRequest(String index, String type, String id,
+ String version, String payload) {
+
+ StringBuilder requestPayload = new StringBuilder(128);
+
+ requestPayload.append(String.format(BULK_IMPORT_INDEX_TEMPLATE, index, type, id, version));
+ requestPayload.append(payload).append("\n");
+
+ return requestPayload.toString();
+
+ }
+
+ public OperationResult retrieveEntityById(String host, String port, String indexName,
+ String docType, String resourceUrl) {
+ String esUrl =
+ String.format("http://%s:%s/%s/%s/%s", host, port, indexName, docType, resourceUrl);
+ return doGet(esUrl, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/sparky/dal/NetworkTransaction.java b/src/main/java/org/onap/aai/sparky/dal/NetworkTransaction.java
index da24c80..fbc89c3 100644
--- a/src/main/java/org/onap/aai/sparky/dal/NetworkTransaction.java
+++ b/src/main/java/org/onap/aai/sparky/dal/NetworkTransaction.java
@@ -22,9 +22,10 @@
*/
package org.onap.aai.sparky.dal;
+import org.onap.aai.restclient.client.OperationResult;
import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
import org.onap.aai.sparky.dal.rest.HttpMethod;
-import org.onap.aai.sparky.dal.rest.OperationResult;
+
/**
* The Class NetworkTransaction.
@@ -37,12 +38,16 @@ public class NetworkTransaction {
private String link;
+ private String queryParameters;
+
private HttpMethod operationType;
private OxmEntityDescriptor descriptor;
private long createdTimeStampInMs;
+ private long opTimeInMs;
+
private long taskAgeInMs;
/**
@@ -50,6 +55,7 @@ public class NetworkTransaction {
*/
public NetworkTransaction() {
this.createdTimeStampInMs = System.currentTimeMillis();
+ this.opTimeInMs = 0L;
}
/**
@@ -64,6 +70,7 @@ public class NetworkTransaction {
this.operationType = method;
this.entityType = entityType;
this.operationResult = or;
+ this.opTimeInMs = 0L;
}
public HttpMethod getOperationType() {
@@ -109,6 +116,22 @@ public class NetworkTransaction {
this.link = link;
}
+ public String getQueryParameters() {
+ return queryParameters;
+ }
+
+ public void setQueryParameters(String queryParameters) {
+ this.queryParameters = queryParameters;
+ }
+
+ public long getOpTimeInMs() {
+ return opTimeInMs;
+ }
+
+ public void setOpTimeInMs(long opTimeInMs) {
+ this.opTimeInMs = opTimeInMs;
+ }
+
public OxmEntityDescriptor getDescriptor() {
return descriptor;
}
diff --git a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryAdapter.java b/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryAdapter.java
deleted file mode 100644
index 08a6584..0000000
--- a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryAdapter.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-package org.onap.aai.sparky.dal.aai;
-
-import java.io.IOException;
-import java.net.URLEncoder;
-import java.nio.ByteBuffer;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import org.apache.http.client.utils.URIBuilder;
-import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
-import org.onap.aai.sparky.config.oxm.OxmModelLoader;
-import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
-import org.onap.aai.sparky.dal.aai.config.ActiveInventoryRestConfig;
-import org.onap.aai.sparky.dal.aai.enums.RestAuthenticationMode;
-import org.onap.aai.sparky.dal.exception.ElasticSearchOperationException;
-import org.onap.aai.sparky.dal.rest.OperationResult;
-import org.onap.aai.sparky.dal.rest.RestClientBuilder;
-import org.onap.aai.sparky.dal.rest.RestfulDataAccessor;
-import org.onap.aai.sparky.logging.AaiUiMsgs;
-import org.onap.aai.sparky.security.SecurityContextFactory;
-import org.onap.aai.sparky.util.NodeUtils;
-import org.onap.aai.cl.api.Logger;
-import org.onap.aai.cl.eelf.LoggerFactory;
-
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.WebResource.Builder;
-
-
-/**
- * The Class ActiveInventoryAdapter.
- */
-
-/**
- * @author davea
- *
- */
-public class ActiveInventoryAdapter extends RestfulDataAccessor
- implements ActiveInventoryDataProvider {
-
- private static final Logger LOG =
- LoggerFactory.getInstance().getLogger(ActiveInventoryAdapter.class);
-
- private static final String HEADER_TRANS_ID = "X-TransactionId";
- private static final String HEADER_FROM_APP_ID = "X-FromAppId";
- private static final String HEADER_AUTHORIZATION = "Authorization";
-
- private static final String TRANSACTION_ID_PREFIX = "txnId-";
- private static final String UI_APP_NAME = "AAI-UI";
-
-
- private ActiveInventoryConfig config;
-
- /**
- * Instantiates a new active inventory adapter.
- *
- * @param restClientBuilder the rest client builder
- * @throws ElasticSearchOperationException the elastic search operation exception
- * @throws IOException Signals that an I/O exception has occurred.
- */
- public ActiveInventoryAdapter(RestClientBuilder restClientBuilder)
- throws ElasticSearchOperationException, IOException {
- super(restClientBuilder);
-
- try {
- this.config = ActiveInventoryConfig.getConfig();
- } catch (Exception exc) {
- throw new ElasticSearchOperationException("Error getting active inventory configuration",
- exc);
- }
-
- clientBuilder.setUseHttps(true);
-
- clientBuilder.setValidateServerHostname(config.getAaiSslConfig().isValidateServerHostName());
-
- SecurityContextFactory sslContextFactory = clientBuilder.getSslContextFactory();
-
- sslContextFactory.setServerCertificationChainValidationEnabled(
- config.getAaiSslConfig().isValidateServerCertificateChain());
-
- if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_CERT) {
- sslContextFactory.setClientCertFileName(config.getAaiSslConfig().getKeystoreFilename());
- sslContextFactory.setClientCertPassword(config.getAaiSslConfig().getKeystorePassword());
- sslContextFactory.setTrustStoreFileName(config.getAaiSslConfig().getTruststoreFilename());
- }
-
- clientBuilder.setConnectTimeoutInMs(config.getAaiRestConfig().getConnectTimeoutInMs());
- clientBuilder.setReadTimeoutInMs(config.getAaiRestConfig().getReadTimeoutInMs());
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.onap.aai.sparky.dal.rest.RestfulDataAccessor#setClientDefaults(com.sun.jersey.api.client.
- * Client, java.lang.String, java.lang.String, java.lang.String)
- */
- @Override
- protected Builder setClientDefaults(Client client, String url, String payloadContentType,
- String acceptContentType) {
- Builder builder = super.setClientDefaults(client, url, payloadContentType, acceptContentType);
-
- builder = builder.header(HEADER_FROM_APP_ID, UI_APP_NAME);
- byte bytes[] = new byte[6];
- txnIdGenerator.nextBytes(bytes);
- builder =
- builder.header(HEADER_TRANS_ID, TRANSACTION_ID_PREFIX + ByteBuffer.wrap(bytes).getInt());
-
- if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC) {
- builder = builder.header(HEADER_AUTHORIZATION,
- config.getAaiSslConfig().getBasicAuthenticationCredentials());
- }
-
- return builder;
- }
-
- /**
- * Gets the full url.
- *
- * @param resourceUrl the resource url
- * @return the full url
- * @throws Exception the exception
- */
- private String getFullUrl(String resourceUrl) throws Exception {
- ActiveInventoryRestConfig aaiRestConfig = ActiveInventoryConfig.getConfig().getAaiRestConfig();
- final String host = aaiRestConfig.getHost();
- final String port = aaiRestConfig.getPort();
- final String basePath = aaiRestConfig.getResourceBasePath();
- return String.format("https://%s:%s%s%s", host, port, basePath, resourceUrl);
- }
-
- public String getGenericQueryForSelfLink(String startNodeType, List queryParams)
- throws Exception {
-
- URIBuilder urlBuilder = new URIBuilder(getFullUrl("/search/generic-query"));
-
- for (String queryParam : queryParams) {
- urlBuilder.addParameter("key", queryParam);
- }
-
- urlBuilder.addParameter("start-node-type", startNodeType);
- urlBuilder.addParameter("include", startNodeType);
-
- final String constructedLink = urlBuilder.toString();
-
- // TODO: debug log for constructed link
-
- return constructedLink;
-
- }
-
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinksByEntityType(java.lang.
- * String)
- */
- @Override
- public OperationResult getSelfLinksByEntityType(String entityType) throws Exception {
-
- /*
- * For this one, I want to dynamically construct the nodes-query for self-link discovery as a
- * utility method that will use the OXM model entity data to drive the query as well.
- */
-
- if (entityType == null) {
- throw new NullPointerException(
- "Failed to getSelfLinksByEntityType() because entityType is null");
- }
-
- OxmEntityDescriptor entityDescriptor =
- OxmModelLoader.getInstance().getEntityDescriptor(entityType);
-
- if (entityDescriptor == null) {
- throw new NoSuchElementException("Failed to getSelfLinksByEntityType() because could"
- + " not find entity descriptor from OXM with type = " + entityType);
- }
-
- String link = null;
- final String primaryKeyStr =
- NodeUtils.concatArray(entityDescriptor.getPrimaryKeyAttributeName(), "/");
-
- link = getFullUrl("/search/nodes-query?search-node-type=" + entityType + "&filter="
- + primaryKeyStr + ":EXISTS");
-
-
-
- return doGet(link, "application/json");
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinkForEntity(java.lang.String,
- * java.lang.String, java.lang.String)
- */
- @Override
- public OperationResult getSelfLinkForEntity(String entityType, String primaryKeyName,
- String primaryKeyValue) throws Exception {
-
- if (entityType == null) {
- throw new NullPointerException("Failed to getSelfLinkForEntity() because entityType is null");
- }
-
- if (primaryKeyName == null) {
- throw new NullPointerException(
- "Failed to getSelfLinkForEntity() because primaryKeyName is null");
- }
-
- if (primaryKeyValue == null) {
- throw new NullPointerException(
- "Failed to getSelfLinkForEntity() because primaryKeyValue is null");
- }
-
-
- /*
- * Try to protect ourselves from illegal URI formatting exceptions caused by characters that
- * aren't natively supported in a URI, but can be escaped to make them legal.
- */
-
- String encodedEntityType = URLEncoder.encode(entityType, "UTF-8");
- String encodedPrimaryKeyName = URLEncoder.encode(primaryKeyName, "UTF-8");
- String encodedPrimaryKeyValue = URLEncoder.encode(primaryKeyValue, "UTF-8");
-
- String link = null;
-
- if ("service-instance".equals(entityType)) {
-
- link = getFullUrl("/search/generic-query?key=" + encodedEntityType + "."
- + encodedPrimaryKeyName + ":" + encodedPrimaryKeyValue + "&start-node-type="
- + encodedEntityType + "&include=customer&depth=2");
-
- } else {
-
- link =
- getFullUrl("/search/generic-query?key=" + encodedEntityType + "." + encodedPrimaryKeyName
- + ":" + encodedPrimaryKeyValue + "&start-node-type=" + encodedEntityType);
-
- }
-
- return queryActiveInventoryWithRetries(link, "application/json",
- this.config.getAaiRestConfig().getNumRequestRetries());
-
- }
-
-
- /**
- * Our retry conditions should be very specific.
- *
- * @param r the r
- * @return true, if successful
- */
- private boolean shouldRetryRequest(OperationResult r) {
-
- if (r == null) {
- return true;
- }
-
- int rc = r.getResultCode();
-
- if (rc == 200) {
- return false;
- }
-
- if (rc == 404) {
- return false;
- }
-
- return true;
-
- }
-
- /**
- * Query active inventory.
- *
- * @param url the url
- * @param acceptContentType the accept content type
- * @return the operation result
- */
- // package protected for test classes instead of private
- OperationResult queryActiveInventory(String url, String acceptContentType) {
- return doGet(url, acceptContentType);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#queryActiveInventoryWithRetries(java.
- * lang.String, java.lang.String, int)
- */
- @Override
- public OperationResult queryActiveInventoryWithRetries(String url, String responseType,
- int numRetries) {
-
- OperationResult result = null;
-
- for (int x = 0; x < numRetries; x++) {
-
- LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(x + 1));
-
- result = queryActiveInventory(url, responseType);
-
- /**
- * Record number of times we have attempted the request to later summarize how many times we
- * are generally retrying over thousands of messages in a sync.
- *
- * If the number of retries is surprisingly high, then we need to understand why that is as
- * the number of retries is also causing a heavier load on AAI beyond the throttling controls
- * we already have in place in term of the transaction rate controller and number of
- * parallelized threads per task processor.
- */
-
- result.setNumRequestRetries(x);
-
- if (!shouldRetryRequest(result)) {
-
- /*
- * if (myConfig.getAaiRestConfig().isCacheEnabled()) {
- *
- * CachedHttpRequest cachedRequest = new CachedHttpRequest();
- * cachedRequest.setHttpRequestMethod("GET"); cachedRequest.setPayload("");
- * cachedRequest.setPayloadMimeType(""); cachedRequest.setUrl(url);
- * cachedRequest.setOperationType( TransactionStorageType.ACTIVE_INVENTORY_QUERY.getIndex()
- * );
- *
- * CachedHttpResponse cachedResponse = new CachedHttpResponse();
- * cachedResponse.setPayload(result.getResult());
- * cachedResponse.setPayloadMimeType("application/json");
- * cachedResponse.setStatusCode(result.getResultCode());
- *
- * CachedHttpTransaction txn = new CachedHttpTransaction(cachedRequest, cachedResponse);
- * storageProvider.persistTransaction(txn);
- *
- * }
- */
-
-
- result.setResolvedLinkFromServer(true);
- LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(x + 1));
-
- return result;
- }
-
- try {
- /*
- * Sleep between re-tries to be nice to the target system.
- */
- Thread.sleep(50);
- } catch (InterruptedException exc) {
- LOG.error(AaiUiMsgs.QUERY_AAI_WAIT_INTERRUPTION, exc.getLocalizedMessage());
- break;
- }
- LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(x + 1));
- }
-
-
- result.setResolvedLinkFailure(true);
- LOG.info(AaiUiMsgs.QUERY_AAI_RETRY_MAXED_OUT, url);
-
- return result;
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.onap.aai.sparky.dal.rest.RestfulDataAccessor#shutdown()
- */
- @Override
- public void shutdown() {
- // TODO Auto-generated method stub
-
- if (entityCache != null) {
- entityCache.shutdown();
- }
-
- }
-
-
-}
diff --git a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryDataProvider.java b/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryDataProvider.java
index 21fb4e6..75e7a54 100644
--- a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryDataProvider.java
+++ b/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryDataProvider.java
@@ -30,6 +30,11 @@ import org.onap.aai.sparky.dal.rest.RestDataProvider;
/**
* The Interface ActiveInventoryDataProvider.
*/
+
+/*
+ * TODO: DELETE ME
+ */
+
public interface ActiveInventoryDataProvider extends RestDataProvider {
/**
@@ -81,7 +86,7 @@ public interface ActiveInventoryDataProvider extends RestDataProvider {
/*
* (non-Javadoc)
*
- * @see org.onap.aai.sparky.dal.rest.RestDataProvider#shutdown()
+ * @see org.openecomp.sparky.dal.rest.RestDataProvider#shutdown()
*/
@Override
void shutdown();
diff --git a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryEntityStatistics.java b/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryEntityStatistics.java
index c1ed906..6ffebef 100644
--- a/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryEntityStatistics.java
+++ b/src/main/java/org/onap/aai/sparky/dal/aai/ActiveInventoryEntityStatistics.java
@@ -29,10 +29,9 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
-import org.onap.aai.sparky.config.oxm.OxmEntityDescriptor;
-import org.onap.aai.sparky.config.oxm.OxmModelLoader;
+import org.onap.aai.restclient.client.OperationResult;
import org.onap.aai.sparky.dal.NetworkTransaction;
-import org.onap.aai.sparky.dal.rest.OperationResult;
+
/**
* The Class ActiveInventoryEntityStatistics.
@@ -51,9 +50,6 @@ public class ActiveInventoryEntityStatistics {
private static final String ERROR = "Error";
- private OxmModelLoader loader;
-
-
private Map> activeInventoryEntityStatistics;
/**
@@ -76,30 +72,6 @@ public class ActiveInventoryEntityStatistics {
}
- /*
- * private void createSearchableActiveInventoryEntityStatistics() {
- *
- * Map descriptors = loader.getSearchableEntityDescriptors();
- *
- * if(descriptors == null) { return; }
- *
- * OxmEntityDescriptor d = null; for ( String key : descriptors.keySet() ) { d =
- * descriptors.get(key); activeInventoryEntityStatistics.put(d.getEntityName(),
- * createEntityOpStats()); }
- *
- * }
- */
-
- /*
- * private void createCrossEntityReferenceActiveInventoryEntityStatistics() {
- *
- * Map descriptors = loader.getCrossReferenceEntityDescriptors();
- *
- *
- * }
- */
-
-
/**
* Initializecreate active inventory entity statistics.
*/
@@ -126,11 +98,8 @@ public class ActiveInventoryEntityStatistics {
*
* @param loader the loader
*/
- public ActiveInventoryEntityStatistics(OxmModelLoader loader) {
- this.loader = loader;
+ public ActiveInventoryEntityStatistics() {
activeInventoryEntityStatistics = new HashMap>();
- // createSearchableActiveInventoryEntityStatistics();
- // createCrossEntityReferenceActiveInventoryEntityStatistics();
reset();
}
@@ -139,21 +108,29 @@ public class ActiveInventoryEntityStatistics {
*
* @param descriptors the descriptors
*/
- public void initializeCountersFromOxmEntityDescriptors(
- Map