From e07d5b8dc0801583518b4f27ce6b8f3b56bcf206 Mon Sep 17 00:00:00 2001 From: "Lee, Tian (tl5884)" Date: Fri, 1 Mar 2019 16:03:03 +0000 Subject: Add elasticsearch with searchguard Dockerfile Add Dockerfile that produces an image of ElasticSearch with SearchGuard plugin pre-installed, and restructure the Maven project to build both the old search-data-service Dockerfile and the new elasticsearch-sg Dockerfile. Change-Id: Iff7cb79e3c09da78b6233422f40cb03eeef5bfdb Issue-ID: AAI-2203 Signed-off-by: Lee, Tian (tl5884) --- License.txt | 18 - bundleconfig-local/etc/logback.xml | 177 --- elasticsearch-sg/pom.xml | 81 ++ elasticsearch-sg/src/main/docker/Dockerfile | 10 + pom.xml | 475 +------ search-data-service/License.txt | 18 + .../bundleconfig-local/etc/logback.xml | 177 +++ search-data-service/pom.xml | 461 +++++++ search-data-service/src/main/bin/start.sh | 33 + search-data-service/src/main/docker/Dockerfile | 27 + .../src/main/java/org/onap/aai/sa/Application.java | 58 + .../org/onap/aai/sa/auth/SearchDbServiceAuth.java | 45 + .../onap/aai/sa/auth/SearchDbServiceAuthCore.java | 212 +++ .../onap/aai/sa/rest/AnalysisConfiguration.java | 229 ++++ .../java/org/onap/aai/sa/rest/AnalyzerApi.java | 161 +++ .../main/java/org/onap/aai/sa/rest/ApiUtils.java | 153 +++ .../main/java/org/onap/aai/sa/rest/BulkApi.java | 209 +++ .../java/org/onap/aai/sa/rest/BulkMetaData.java | 49 + .../java/org/onap/aai/sa/rest/BulkOperation.java | 59 + .../java/org/onap/aai/sa/rest/BulkRequest.java | 110 ++ .../main/java/org/onap/aai/sa/rest/Document.java | 57 + .../java/org/onap/aai/sa/rest/DocumentApi.java | 599 +++++++++ .../main/java/org/onap/aai/sa/rest/IndexApi.java | 402 ++++++ .../org/onap/aai/sa/rest/SearchServiceApi.java | 216 +++ .../org/onap/aai/sa/rest/SettingConfiguration.java | 84 ++ .../sa/searchdbabstraction/RestEchoService.java | 47 + .../elasticsearch/config/ElasticSearchConfig.java | 240 ++++ .../elasticsearch/dao/DocumentStoreDataEntity.java | 31 + .../dao/DocumentStoreDataEntityImpl.java | 60 + .../elasticsearch/dao/DocumentStoreInterface.java | 70 + .../dao/ElasticSearchBulkOperationResult.java | 66 + .../elasticsearch/dao/ElasticSearchCause.java | 43 + .../elasticsearch/dao/ElasticSearchError.java | 69 + .../dao/ElasticSearchHttpController.java | 1410 ++++++++++++++++++++ .../dao/ElasticSearchHttpsController.java | 148 ++ .../dao/ElasticSearchOperationStatus.java | 112 ++ .../elasticsearch/dao/ElasticSearchResultItem.java | 149 +++ .../dao/ElasticSearchShardStatus.java | 59 + .../exception/DocumentStoreOperationException.java | 53 + .../entity/AggregationBucket.java | 75 ++ .../entity/AggregationResult.java | 74 + .../entity/AggregationResults.java | 41 + .../sa/searchdbabstraction/entity/Document.java | 61 + .../entity/DocumentOperationResult.java | 40 + .../sa/searchdbabstraction/entity/ErrorResult.java | 55 + .../entity/OperationResult.java | 78 ++ .../entity/OperationResultBuilder.java | 90 ++ .../sa/searchdbabstraction/entity/SearchHit.java | 48 + .../sa/searchdbabstraction/entity/SearchHits.java | 50 + .../entity/SearchOperationResult.java | 59 + .../sa/searchdbabstraction/entity/SuggestHit.java | 57 + .../sa/searchdbabstraction/entity/SuggestHits.java | 50 + .../searchdbabstraction/logging/SearchDbMsgs.java | 182 +++ .../searchapi/AbstractAggregation.java | 75 ++ .../searchdbabstraction/searchapi/Aggregation.java | 61 + .../searchapi/AggregationStatement.java | 173 +++ .../searchapi/DateHistogramAggregation.java | 117 ++ .../searchdbabstraction/searchapi/DateRange.java | 115 ++ .../searchapi/DateRangeAggregation.java | 130 ++ .../sa/searchdbabstraction/searchapi/Filter.java | 183 +++ .../searchapi/GroupByAggregation.java | 70 + .../searchdbabstraction/searchapi/ParsedQuery.java | 120 ++ .../sa/searchdbabstraction/searchapi/Query.java | 90 ++ .../searchapi/QueryStatement.java | 138 ++ .../searchdbabstraction/searchapi/RangeQuery.java | 336 +++++ .../searchapi/SearchStatement.java | 319 +++++ .../aai/sa/searchdbabstraction/searchapi/Sort.java | 72 + .../searchapi/SuggestionStatement.java | 93 ++ .../searchdbabstraction/searchapi/TermQuery.java | 342 +++++ .../searchdbabstraction/service/SearchService.java | 54 + .../util/AggregationParsingUtil.java | 103 ++ .../util/DocumentSchemaUtil.java | 134 ++ .../util/ElasticSearchPayloadTranslator.java | 101 ++ .../util/SearchDbConstants.java | 53 + .../src/main/resources/application.properties | 4 + search-data-service/src/main/resources/banner.txt | 5 + .../resources/json/schema/analyzer.schema.json | 29 + .../json/schema/document-field.schema.json | 37 + .../resources/json/schema/document.schema.json | 15 + .../main/resources/json/schema/filter.schema.json | 17 + .../main/resources/logging/SearchDbMsgs.properties | 123 ++ .../onap/aai/sa/auth/SearchDbServiceAuthTest.java | 86 ++ .../java/org/onap/aai/sa/rest/ApiUtilsTest.java | 37 + .../java/org/onap/aai/sa/rest/BulkApiTest.java | 86 ++ .../java/org/onap/aai/sa/rest/BulkRequestTest.java | 149 +++ .../java/org/onap/aai/sa/rest/DocumentApiTest.java | 206 +++ .../org/onap/aai/sa/rest/DocumentSchemaTest.java | 99 ++ .../java/org/onap/aai/sa/rest/DocumentTest.java | 727 ++++++++++ .../java/org/onap/aai/sa/rest/IndexApiTest.java | 280 ++++ .../onap/aai/sa/rest/SearchServiceApiHarness.java | 164 +++ .../onap/aai/sa/rest/SettingConfigurationTest.java | 57 + .../org/onap/aai/sa/rest/StubEsController.java | 266 ++++ .../test/java/org/onap/aai/sa/rest/TestUtils.java | 63 + .../config/ElasticSearchConfigTest.java | 53 + .../dao/AggregationResponseParsingTest.java | 99 ++ .../dao/ElasticSearchHttpControllerTest.java | 330 +++++ .../dao/ElasticSearchResultItemTest.java | 119 ++ .../searchapi/AggregationStatementTest.java | 154 +++ .../searchapi/AggregationTest.java | 51 + .../searchapi/DateHistogramAggregationTest.java | 78 ++ .../searchapi/DateRangeAggregationTest.java | 69 + .../searchapi/DateRangeTest.java | 75 ++ .../searchdbabstraction/searchapi/FilterTest.java | 43 + .../searchapi/GroupByAggregationTest.java | 62 + .../searchdbabstraction/searchapi/QueryTest.java | 368 +++++ .../searchapi/RangeQueryTest.java | 155 +++ .../searchapi/SearchStatementTest.java | 211 +++ .../sa/searchdbabstraction/searchapi/SortTest.java | 49 + .../searchapi/TermQueryTest.java | 63 + .../util/ElasticSearchPayloadTranslatorTest.java | 55 + .../src/test/resources/json/analysis-config.json | 21 + .../src/test/resources/json/bulk-ops-invalid.json | 32 + .../src/test/resources/json/bulk-ops-valid.json | 31 + .../resources/json/dynamic-custom-template.json | 12 + .../src/test/resources/json/dynamicIndex.json | 17 + .../resources/json/es-payload-translation.json | 16 + .../src/test/resources/json/filter-config.json | 7 + .../src/test/resources/json/index-mapping.json | 28 + .../src/test/resources/json/nested-document.json | 49 + .../json/queries/query-with-subrange.json | 14 + .../json/queries/simple-parsed-query.json | 10 + .../src/test/resources/json/search_policy.json | 63 + .../src/test/resources/json/settings-config.json | 9 + .../src/test/resources/json/simpleDocument.json | 17 + .../test/resources/json/tier-support-document.json | 30 + src/main/bin/start.sh | 33 - src/main/docker/Dockerfile | 27 - src/main/java/org/onap/aai/sa/Application.java | 58 - .../org/onap/aai/sa/auth/SearchDbServiceAuth.java | 45 - .../onap/aai/sa/auth/SearchDbServiceAuthCore.java | 212 --- .../onap/aai/sa/rest/AnalysisConfiguration.java | 229 ---- .../java/org/onap/aai/sa/rest/AnalyzerApi.java | 161 --- src/main/java/org/onap/aai/sa/rest/ApiUtils.java | 153 --- src/main/java/org/onap/aai/sa/rest/BulkApi.java | 209 --- .../java/org/onap/aai/sa/rest/BulkMetaData.java | 49 - .../java/org/onap/aai/sa/rest/BulkOperation.java | 59 - .../java/org/onap/aai/sa/rest/BulkRequest.java | 110 -- src/main/java/org/onap/aai/sa/rest/Document.java | 57 - .../java/org/onap/aai/sa/rest/DocumentApi.java | 599 --------- src/main/java/org/onap/aai/sa/rest/IndexApi.java | 402 ------ .../org/onap/aai/sa/rest/SearchServiceApi.java | 216 --- .../org/onap/aai/sa/rest/SettingConfiguration.java | 84 -- .../sa/searchdbabstraction/RestEchoService.java | 47 - .../elasticsearch/config/ElasticSearchConfig.java | 240 ---- .../elasticsearch/dao/DocumentStoreDataEntity.java | 31 - .../dao/DocumentStoreDataEntityImpl.java | 60 - .../elasticsearch/dao/DocumentStoreInterface.java | 70 - .../dao/ElasticSearchBulkOperationResult.java | 66 - .../elasticsearch/dao/ElasticSearchCause.java | 43 - .../elasticsearch/dao/ElasticSearchError.java | 69 - .../dao/ElasticSearchHttpController.java | 1410 -------------------- .../dao/ElasticSearchHttpsController.java | 148 -- .../dao/ElasticSearchOperationStatus.java | 112 -- .../elasticsearch/dao/ElasticSearchResultItem.java | 149 --- .../dao/ElasticSearchShardStatus.java | 59 - .../exception/DocumentStoreOperationException.java | 53 - .../entity/AggregationBucket.java | 75 -- .../entity/AggregationResult.java | 74 - .../entity/AggregationResults.java | 41 - .../sa/searchdbabstraction/entity/Document.java | 61 - .../entity/DocumentOperationResult.java | 40 - .../sa/searchdbabstraction/entity/ErrorResult.java | 55 - .../entity/OperationResult.java | 78 -- .../entity/OperationResultBuilder.java | 90 -- .../sa/searchdbabstraction/entity/SearchHit.java | 48 - .../sa/searchdbabstraction/entity/SearchHits.java | 50 - .../entity/SearchOperationResult.java | 59 - .../sa/searchdbabstraction/entity/SuggestHit.java | 57 - .../sa/searchdbabstraction/entity/SuggestHits.java | 50 - .../searchdbabstraction/logging/SearchDbMsgs.java | 182 --- .../searchapi/AbstractAggregation.java | 75 -- .../searchdbabstraction/searchapi/Aggregation.java | 61 - .../searchapi/AggregationStatement.java | 173 --- .../searchapi/DateHistogramAggregation.java | 117 -- .../searchdbabstraction/searchapi/DateRange.java | 115 -- .../searchapi/DateRangeAggregation.java | 130 -- .../sa/searchdbabstraction/searchapi/Filter.java | 183 --- .../searchapi/GroupByAggregation.java | 70 - .../searchdbabstraction/searchapi/ParsedQuery.java | 120 -- .../sa/searchdbabstraction/searchapi/Query.java | 90 -- .../searchapi/QueryStatement.java | 138 -- .../searchdbabstraction/searchapi/RangeQuery.java | 336 ----- .../searchapi/SearchStatement.java | 319 ----- .../aai/sa/searchdbabstraction/searchapi/Sort.java | 72 - .../searchapi/SuggestionStatement.java | 93 -- .../searchdbabstraction/searchapi/TermQuery.java | 342 ----- .../searchdbabstraction/service/SearchService.java | 54 - .../util/AggregationParsingUtil.java | 103 -- .../util/DocumentSchemaUtil.java | 134 -- .../util/ElasticSearchPayloadTranslator.java | 101 -- .../util/SearchDbConstants.java | 53 - src/main/resources/application.properties | 4 - src/main/resources/banner.txt | 5 - .../resources/json/schema/analyzer.schema.json | 29 - .../json/schema/document-field.schema.json | 37 - .../resources/json/schema/document.schema.json | 15 - src/main/resources/json/schema/filter.schema.json | 17 - src/main/resources/logging/SearchDbMsgs.properties | 123 -- .../onap/aai/sa/auth/SearchDbServiceAuthTest.java | 86 -- .../java/org/onap/aai/sa/rest/ApiUtilsTest.java | 37 - .../java/org/onap/aai/sa/rest/BulkApiTest.java | 86 -- .../java/org/onap/aai/sa/rest/BulkRequestTest.java | 149 --- .../java/org/onap/aai/sa/rest/DocumentApiTest.java | 206 --- .../org/onap/aai/sa/rest/DocumentSchemaTest.java | 99 -- .../java/org/onap/aai/sa/rest/DocumentTest.java | 727 ---------- .../java/org/onap/aai/sa/rest/IndexApiTest.java | 280 ---- .../onap/aai/sa/rest/SearchServiceApiHarness.java | 164 --- .../onap/aai/sa/rest/SettingConfigurationTest.java | 57 - .../org/onap/aai/sa/rest/StubEsController.java | 266 ---- src/test/java/org/onap/aai/sa/rest/TestUtils.java | 63 - .../config/ElasticSearchConfigTest.java | 53 - .../dao/AggregationResponseParsingTest.java | 99 -- .../dao/ElasticSearchHttpControllerTest.java | 330 ----- .../dao/ElasticSearchResultItemTest.java | 119 -- .../searchapi/AggregationStatementTest.java | 154 --- .../searchapi/AggregationTest.java | 51 - .../searchapi/DateHistogramAggregationTest.java | 78 -- .../searchapi/DateRangeAggregationTest.java | 69 - .../searchapi/DateRangeTest.java | 75 -- .../searchdbabstraction/searchapi/FilterTest.java | 43 - .../searchapi/GroupByAggregationTest.java | 62 - .../searchdbabstraction/searchapi/QueryTest.java | 368 ----- .../searchapi/RangeQueryTest.java | 155 --- .../searchapi/SearchStatementTest.java | 211 --- .../sa/searchdbabstraction/searchapi/SortTest.java | 49 - .../searchapi/TermQueryTest.java | 63 - .../util/ElasticSearchPayloadTranslatorTest.java | 55 - src/test/resources/json/analysis-config.json | 21 - src/test/resources/json/bulk-ops-invalid.json | 32 - src/test/resources/json/bulk-ops-valid.json | 31 - .../resources/json/dynamic-custom-template.json | 12 - src/test/resources/json/dynamicIndex.json | 17 - .../resources/json/es-payload-translation.json | 16 - src/test/resources/json/filter-config.json | 7 - src/test/resources/json/index-mapping.json | 28 - src/test/resources/json/nested-document.json | 49 - .../json/queries/query-with-subrange.json | 14 - .../json/queries/simple-parsed-query.json | 10 - src/test/resources/json/search_policy.json | 63 - src/test/resources/json/settings-config.json | 9 - src/test/resources/json/simpleDocument.json | 17 - src/test/resources/json/tier-support-document.json | 30 - 242 files changed, 14714 insertions(+), 14581 deletions(-) delete mode 100644 License.txt delete mode 100644 bundleconfig-local/etc/logback.xml create mode 100644 elasticsearch-sg/pom.xml create mode 100644 elasticsearch-sg/src/main/docker/Dockerfile create mode 100644 search-data-service/License.txt create mode 100644 search-data-service/bundleconfig-local/etc/logback.xml create mode 100644 search-data-service/pom.xml create mode 100644 search-data-service/src/main/bin/start.sh create mode 100644 search-data-service/src/main/docker/Dockerfile create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/Application.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/ApiUtils.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/BulkApi.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/BulkOperation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/BulkRequest.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/Document.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/DocumentApi.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/IndexApi.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java create mode 100644 search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java create mode 100644 search-data-service/src/main/resources/application.properties create mode 100644 search-data-service/src/main/resources/banner.txt create mode 100644 search-data-service/src/main/resources/json/schema/analyzer.schema.json create mode 100644 search-data-service/src/main/resources/json/schema/document-field.schema.json create mode 100644 search-data-service/src/main/resources/json/schema/document.schema.json create mode 100644 search-data-service/src/main/resources/json/schema/filter.schema.json create mode 100644 search-data-service/src/main/resources/logging/SearchDbMsgs.properties create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/StubEsController.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/rest/TestUtils.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java create mode 100644 search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java create mode 100644 search-data-service/src/test/resources/json/analysis-config.json create mode 100644 search-data-service/src/test/resources/json/bulk-ops-invalid.json create mode 100644 search-data-service/src/test/resources/json/bulk-ops-valid.json create mode 100644 search-data-service/src/test/resources/json/dynamic-custom-template.json create mode 100644 search-data-service/src/test/resources/json/dynamicIndex.json create mode 100644 search-data-service/src/test/resources/json/es-payload-translation.json create mode 100644 search-data-service/src/test/resources/json/filter-config.json create mode 100644 search-data-service/src/test/resources/json/index-mapping.json create mode 100644 search-data-service/src/test/resources/json/nested-document.json create mode 100644 search-data-service/src/test/resources/json/queries/query-with-subrange.json create mode 100644 search-data-service/src/test/resources/json/queries/simple-parsed-query.json create mode 100644 search-data-service/src/test/resources/json/search_policy.json create mode 100644 search-data-service/src/test/resources/json/settings-config.json create mode 100644 search-data-service/src/test/resources/json/simpleDocument.json create mode 100644 search-data-service/src/test/resources/json/tier-support-document.json delete mode 100644 src/main/bin/start.sh delete mode 100644 src/main/docker/Dockerfile delete mode 100644 src/main/java/org/onap/aai/sa/Application.java delete mode 100644 src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java delete mode 100644 src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/ApiUtils.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/BulkApi.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/BulkMetaData.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/BulkOperation.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/BulkRequest.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/Document.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/DocumentApi.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/IndexApi.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java delete mode 100644 src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java delete mode 100644 src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java delete mode 100644 src/main/resources/application.properties delete mode 100644 src/main/resources/banner.txt delete mode 100644 src/main/resources/json/schema/analyzer.schema.json delete mode 100644 src/main/resources/json/schema/document-field.schema.json delete mode 100644 src/main/resources/json/schema/document.schema.json delete mode 100644 src/main/resources/json/schema/filter.schema.json delete mode 100644 src/main/resources/logging/SearchDbMsgs.properties delete mode 100644 src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/BulkApiTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/DocumentTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/IndexApiTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/StubEsController.java delete mode 100644 src/test/java/org/onap/aai/sa/rest/TestUtils.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java delete mode 100644 src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java delete mode 100644 src/test/resources/json/analysis-config.json delete mode 100644 src/test/resources/json/bulk-ops-invalid.json delete mode 100644 src/test/resources/json/bulk-ops-valid.json delete mode 100644 src/test/resources/json/dynamic-custom-template.json delete mode 100644 src/test/resources/json/dynamicIndex.json delete mode 100644 src/test/resources/json/es-payload-translation.json delete mode 100644 src/test/resources/json/filter-config.json delete mode 100644 src/test/resources/json/index-mapping.json delete mode 100644 src/test/resources/json/nested-document.json delete mode 100644 src/test/resources/json/queries/query-with-subrange.json delete mode 100644 src/test/resources/json/queries/simple-parsed-query.json delete mode 100644 src/test/resources/json/search_policy.json delete mode 100644 src/test/resources/json/settings-config.json delete mode 100644 src/test/resources/json/simpleDocument.json delete mode 100644 src/test/resources/json/tier-support-document.json diff --git a/License.txt b/License.txt deleted file mode 100644 index df05b97..0000000 --- a/License.txt +++ /dev/null @@ -1,18 +0,0 @@ -============LICENSE_START======================================================= -org.onap.aai -================================================================================ -Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. -Copyright © 2017-2018 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========================================================= diff --git a/bundleconfig-local/etc/logback.xml b/bundleconfig-local/etc/logback.xml deleted file mode 100644 index 7b90318..0000000 --- a/bundleconfig-local/etc/logback.xml +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - ${errorLogPattern} - - - - - - - - - - - ${logDirectory}/${generalLogName}.log - - ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${errorLogPattern} - - - - - - INFO - - 256 - - - - - - - - ${logDirectory}/${auditLogName}.log - - ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${auditMetricPattern} - - - - 256 - - - - - ${logDirectory}/${metricsLogName}.log - - ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - - ${auditMetricPattern} - - - - - - 256 - - - - - ${logDirectory}/${debugLogName}.log - - ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${errorLogPattern} - - - - - 256 - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch-sg/pom.xml b/elasticsearch-sg/pom.xml new file mode 100644 index 0000000..cd24333 --- /dev/null +++ b/elasticsearch-sg/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + org.onap.aai.search-data-service + elasticsearch-sg + elasticsearch with searchguard + 1.4.0-SNAPSHOT + pom + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-docker-file + process-resources + + copy-resources + + + target + true + + + ${basedir}/src/main/docker + + **/* + + + + + + + + + + com.spotify + docker-maven-plugin + 0.4.11 + + true + docker-hub + ${docker.push.registry}/onap/${project.artifactId} + ${basedir}/target + + latest + + true + + + + + + + \ No newline at end of file diff --git a/elasticsearch-sg/src/main/docker/Dockerfile b/elasticsearch-sg/src/main/docker/Dockerfile new file mode 100644 index 0000000..0ccb31d --- /dev/null +++ b/elasticsearch-sg/src/main/docker/Dockerfile @@ -0,0 +1,10 @@ +# https://github.com/elastic/elasticsearch-docker +FROM docker.elastic.co/elasticsearch/elasticsearch:6.1.2 + +USER elasticsearch + +# Search Guard plugin +RUN elasticsearch-plugin install --batch com.floragunn:search-guard-6:6.1.2-22.3 \ + && chmod +x plugins/search-guard-6/tools/*.sh + +ENTRYPOINT ["/usr/share/elasticsearch/bin/run.sh"] \ No newline at end of file diff --git a/pom.xml b/pom.xml index 65c8d40..3eb4543 100644 --- a/pom.xml +++ b/pom.xml @@ -21,450 +21,31 @@ --> - 4.0.0 - - - spring-boot-starter-parent - org.springframework.boot - 1.5.18.RELEASE - - org.onap.aai - search-data-service - 1.4.0-SNAPSHOT - aai-search-data-service - - - ${basedir}/target - https://nexus.onap.org - 1.8 - ${basedir}/src/main/java-gen - google_checks.xml - - java - jacoco - ${project.build.directory}/surefire-reports - - ${project.build.directory}/coverage-reports/jacoco.exec - - false - ${project.version} - - - - - - com.google.code.gson - gson - 2.8.2 - - - - org.hamcrest - hamcrest-library - 1.3 - test - - - - com.jayway.jsonpath - json-path - 2.2.0 - - - - com.googlecode.json-simple - json-simple - 1.1.1 - - - - org.dom4j - dom4j - 2.1.1 - provided - - - - commons-io - commons-io - 2.4 - - - - org.mockito - mockito-all - 1.10.19 - test - - - - - org.onap.aai.logging-service - common-logging - 1.2.2 - - - - org.onap.aai.logging-service - logging-api - 1.2.2 - - - - org.onap.aai.logging-service - eelf-logging - 1.2.2 - - - - - com.fasterxml.jackson.core - jackson-databind - 2.7.8 - - - - org.apache.directory.studio - org.apache.commons.lang - 2.6 - - - - radeox - radeox - 0.9 - - - - com.github.fge - json-schema-validator - 2.0.0 - - - - org.json - json - 20180130 - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - org.springframework.boot - spring-boot-starter-jetty - - - - org.springframework.boot - spring-boot-starter - - - ch.qos.logback - logback-classic - - - - - - org.springframework.boot - spring-boot-starter-jersey - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - org.springframework.boot - spring-boot-starter-actuator - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.boot - spring-boot-starter-security - - - - - ch.qos.logback - logback-classic - 1.2.1 - - - - ch.qos.logback - logback-core - 1.2.1 - - - - - - - central - Maven 2 repository 2 - http://repo2.maven.org/maven2/ - - - ecomp-releases - ECOMP Release Repository - ${nexusproxy}/content/repositories/releases/ - - - ecomp-snapshots - ECOMP Snapshot Repository - ${nexusproxy}/content/repositories/snapshots/ - - - ecomp-staging - ECOMP Staging Repository - ${nexusproxy}/content/repositories/staging/ - - - - - search-data-service-package - - - org.springframework.boot - spring-boot-maven-plugin - - - - - org.apache.maven.plugins - maven-site-plugin - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.17 - - - - checkstyle - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - groovy-eclipse-compiler - true - 1.8 - 1.8 - - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.0-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.3.4-01 - - - - - com.spotify - docker-maven-plugin - 0.4.11 - - true - docker-hub - ${docker.push.registry}/onap/${project.artifactId} - ${docker.location} - - latest - - true - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ${nexusproxy} - 176c31dfe190a - ecomp-staging - - - - - - org.jsonschema2pojo - jsonschema2pojo-maven-plugin - 0.4.26 - - true - ${basedir}/src/main/resources/json/schema - ${generatedSourceDir} - org.onap.aai.sa.rest - - - - - generate - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - - copy-docker-file - package - - copy-resources - - - target - true - - - ${basedir}/src/main/docker - true - - **/* - - - - ${basedir} - true - - bundleconfig-local/** - - - - ${basedir}/src/main/bin/ - - - - - - - - - com.mycila - license-maven-plugin - 3.0 - -
License.txt
- - src/main/java/** - src/test/java/** - pom.xml - - true -
- - - - check - - validate - - -
- - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.codehaus.mojo - sonar-maven-plugin - 3.2 - - - org.jacoco - jacoco-maven-plugin - 0.7.7.201606060606 - - true - - - - jacoco-initialize-unit-tests - - prepare-agent - - - ${project.build.directory}/coverage-reports/jacoco.exec - - - - - - - - - - maven-clean-plugin - 3.0.0 - - - - ${generatedSourceDir} - - - - -
-
- - - ecomp-releases - ECOMP Release Repository - ${nexusproxy}/content/repositories/releases/ - - - ecomp-snapshots - ECOMP Snapshot Repository - ${nexusproxy}/content/repositories/snapshots/ - - - ecomp-javadoc - dav:https://ecomp-nexus:8443/repository/aai/search-data-service-javadoc/${project.version} - - -
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.onap.aai + search-data-service-agg + aai-search-data-service aggregate pom + 1.4.0-SNAPSHOT + pom + + + search-data-service + elasticsearch-sg + + + + + + com.spotify + docker-maven-plugin + 0.4.11 + + true + + + + + + \ No newline at end of file diff --git a/search-data-service/License.txt b/search-data-service/License.txt new file mode 100644 index 0000000..df05b97 --- /dev/null +++ b/search-data-service/License.txt @@ -0,0 +1,18 @@ +============LICENSE_START======================================================= +org.onap.aai +================================================================================ +Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. +Copyright © 2017-2018 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========================================================= diff --git a/search-data-service/bundleconfig-local/etc/logback.xml b/search-data-service/bundleconfig-local/etc/logback.xml new file mode 100644 index 0000000..7b90318 --- /dev/null +++ b/search-data-service/bundleconfig-local/etc/logback.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${errorLogPattern} + + + + + + + + + + + ${logDirectory}/${generalLogName}.log + + ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + + INFO + + 256 + + + + + + + + ${logDirectory}/${auditLogName}.log + + ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + ${logDirectory}/${metricsLogName}.log + + ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + + ${auditMetricPattern} + + + + + + 256 + + + + + ${logDirectory}/${debugLogName}.log + + ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + 256 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/search-data-service/pom.xml b/search-data-service/pom.xml new file mode 100644 index 0000000..a270914 --- /dev/null +++ b/search-data-service/pom.xml @@ -0,0 +1,461 @@ + + + 4.0.0 + + + spring-boot-starter-parent + org.springframework.boot + 1.5.18.RELEASE + + + org.onap.aai + search-data-service + 1.4.0-SNAPSHOT + aai-search-data-service + + + ${basedir}/target + https://nexus.onap.org + 1.8 + ${basedir}/src/main/java-gen + google_checks.xml + + java + jacoco + ${project.build.directory}/surefire-reports + + ${project.build.directory}/coverage-reports/jacoco.exec + + false + ${project.version} + + + + + + com.google.code.gson + gson + + + + org.hamcrest + hamcrest-library + test + + + + com.jayway.jsonpath + json-path + + + + com.googlecode.json-simple + json-simple + + + + org.dom4j + dom4j + 2.1.1 + provided + + + + commons-io + commons-io + 2.4 + + + + org.mockito + mockito-all + 1.10.19 + test + + + + + org.onap.aai.logging-service + common-logging + 1.2.2 + + + + org.onap.aai.logging-service + logging-api + 1.2.2 + + + + org.onap.aai.logging-service + eelf-logging + 1.2.2 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.directory.studio + org.apache.commons.lang + 2.6 + + + + radeox + radeox + 0.9 + + + + com.github.fge + json-schema-validator + 2.0.0 + + + + org.json + json + 20180130 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.boot + spring-boot-starter + + + ch.qos.logback + logback-classic + + + + + + org.springframework.boot + spring-boot-starter-jersey + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-security + + + + + ch.qos.logback + logback-classic + + + + ch.qos.logback + logback-core + + + + + + + central + Maven 2 repository 2 + http://repo2.maven.org/maven2/ + + + ecomp-releases + ECOMP Release Repository + ${nexusproxy}/content/repositories/releases/ + + + ecomp-snapshots + ECOMP Snapshot Repository + ${nexusproxy}/content/repositories/snapshots/ + + + ecomp-staging + ECOMP Staging Repository + ${nexusproxy}/content/repositories/staging/ + + + + + search-data-service-package + + + org.springframework.boot + spring-boot-maven-plugin + + + + + org.apache.maven.plugins + maven-site-plugin + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + groovy-eclipse-compiler + true + 1.8 + 1.8 + + + + org.codehaus.groovy + groovy-eclipse-compiler + 2.9.0-01 + + + org.codehaus.groovy + groovy-eclipse-batch + 2.3.4-01 + + + + + com.spotify + docker-maven-plugin + 0.4.11 + + true + docker-hub + ${docker.push.registry}/onap/${project.artifactId} + ${docker.location} + + latest + + true + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ${nexusproxy} + 176c31dfe190a + ecomp-staging + + + + + + org.jsonschema2pojo + jsonschema2pojo-maven-plugin + 0.4.26 + + true + ${basedir}/src/main/resources/json/schema + ${generatedSourceDir} + org.onap.aai.sa.rest + + + + + generate + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-docker-file + package + + copy-resources + + + target + true + + + ${basedir}/src/main/docker + true + + **/* + + + + ${basedir} + true + + bundleconfig-local/** + + + + ${basedir}/src/main/bin/ + + + + + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + src/main/java/** + src/test/java/** + pom.xml + + true +
+ + + + check + + validate + + +
+ + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.codehaus.mojo + sonar-maven-plugin + 3.2 + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + true + + + + jacoco-initialize-unit-tests + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco.exec + + + + + + + + + + maven-clean-plugin + + + + ${generatedSourceDir} + + + + +
+
+ + + ecomp-releases + ECOMP Release Repository + ${nexusproxy}/content/repositories/releases/ + + + ecomp-snapshots + ECOMP Snapshot Repository + ${nexusproxy}/content/repositories/snapshots/ + + + ecomp-javadoc + dav:https://ecomp-nexus:8443/repository/aai/search-data-service-javadoc/${project.version} + + +
diff --git a/search-data-service/src/main/bin/start.sh b/search-data-service/src/main/bin/start.sh new file mode 100644 index 0000000..5248a7a --- /dev/null +++ b/search-data-service/src/main/bin/start.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +BASEDIR="/opt/app/search-data-service" +AJSC_HOME="$BASEDIR" +AJSC_CONF_HOME="$AJSC_HOME/bundleconfig/" + +if [ -z "$CONFIG_HOME" ]; then + echo "CONFIG_HOME must be set in order to start up process" + exit 1 +fi + +if [ -z "$KEY_STORE_PASSWORD" ]; then + echo "KEY_STORE_PASSWORD must be set in order to start up process" + exit 1 +fi + +PROPS="-DAJSC_HOME=$AJSC_HOME" +PROPS="$PROPS -DAJSC_CONF_HOME=$AJSC_CONF_HOME" +PROPS="$PROPS -Dlogging.config=$BASEDIR/bundleconfig/etc/logback.xml" +PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME" +PROPS="$PROPS -DKEY_STORE_PASSWORD=$KEY_STORE_PASSWORD" + +if [ ! -z "$TRUST_STORE_PASSWORD" ]; then + PROPS="$PROPS -DTRUST_STORE_PASSWORD=${TRUST_STORE_PASSWORD}" +fi + +if [ ! -z "$TRUST_STORE_LOCATION" ]; then + PROPS="$PROPS -DTRUST_STORE_LOCATION=${TRUST_STORE_LOCATION}" +fi + +JVM_MAX_HEAP=${MAX_HEAP:-1024} + +java $PROPS -jar $BASEDIR/search-data-service-package.jar \ No newline at end of file diff --git a/search-data-service/src/main/docker/Dockerfile b/search-data-service/src/main/docker/Dockerfile new file mode 100644 index 0000000..1a70fd7 --- /dev/null +++ b/search-data-service/src/main/docker/Dockerfile @@ -0,0 +1,27 @@ +FROM ubuntu:14.04 + +ARG MICRO_HOME=/opt/app/search-data-service +ARG BIN_HOME=$MICRO_HOME/bin + +## Install and setup java8 +RUN apt-get update && apt-get install -y software-properties-common +## sudo -E is required to preserve the environment. If you remove that line, it will most like freeze at this step +RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk +## Setup JAVA_HOME, this is useful for docker commandline +ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64 +RUN export JAVA_HOME + +# Build up the deployment folder structure +RUN mkdir -p $MICRO_HOME +RUN mkdir -p $MICRO_HOME/bundleconfig/etc +ADD *.jar $MICRO_HOME/ +RUN mkdir -p $BIN_HOME +COPY *.sh $BIN_HOME +COPY bundleconfig-local $MICRO_HOME/bundleconfig +COPY bundleconfig-local/etc/logback.xml $MICRO_HOME/bundleconfig/etc +RUN chmod 755 $BIN_HOME/* +RUN ln -s /logs $MICRO_HOME/logs + +EXPOSE 9509 9509 + +CMD ["/opt/app/search-data-service/bin/start.sh"] diff --git a/search-data-service/src/main/java/org/onap/aai/sa/Application.java b/search-data-service/src/main/java/org/onap/aai/sa/Application.java new file mode 100644 index 0000000..ad52dfd --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/Application.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa; + +import java.util.HashMap; +import org.eclipse.jetty.util.security.Password; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + public static void main(String[] args) { + String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD"); + if (keyStorePassword == null || keyStorePassword.isEmpty()) { + throw new RuntimeException("Env property KEY_STORE_PASSWORD not set"); + } + HashMap props = new HashMap<>(); + String deobfuscatedKeyStorePassword = keyStorePassword.startsWith("OBF:") ? Password.deobfuscate(keyStorePassword) : keyStorePassword; + props.put("server.ssl.key-store-password", deobfuscatedKeyStorePassword); + + String trustStoreLocation = System.getProperty("TRUST_STORE_LOCATION"); + String trustStorePassword = System.getProperty("TRUST_STORE_PASSWORD"); + if (trustStoreLocation != null && trustStorePassword != null) { + trustStorePassword = trustStorePassword.startsWith("OBF:") ? Password.deobfuscate(trustStorePassword) : trustStorePassword; + props.put("server.ssl.trust-store", trustStoreLocation); + props.put("server.ssl.trust-store-password", trustStorePassword); + } + + String requireClientAuth = System.getenv("REQUIRE_CLIENT_AUTH"); + if (requireClientAuth == null || requireClientAuth.isEmpty()) { + props.put("server.ssl.client-auth", "need"); + }else { + props.put("server.ssl.client-auth", Boolean.valueOf(requireClientAuth)? "need" : "want"); + } + + new Application().configure(new SpringApplicationBuilder(Application.class).properties(props)).run(args); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java b/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java new file mode 100644 index 0000000..199b5ec --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.auth; + +import javax.servlet.http.Cookie; +import org.springframework.http.HttpHeaders; + +public class SearchDbServiceAuth { + + public SearchDbServiceAuth() { // Do not instantiate + } + + public boolean authBasic(String username, String authFunction) { + return SearchDbServiceAuthCore.authorize(username, authFunction); + } + + public String authUser(HttpHeaders headers, String authUser, String authFunction) { + return new SearchDbServiceAuth().authBasic(authUser, authFunction) ? "OK" : "AAI_9101"; + } + + public boolean authCookie(Cookie cookie, String authFunction, StringBuilder username) { + if (cookie == null) { + return false; + } + return SearchDbServiceAuthCore.authorize(username.toString(), authFunction); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java b/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java new file mode 100644 index 0000000..5bab0c0 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java @@ -0,0 +1,212 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.auth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; + +public class SearchDbServiceAuthCore { + + private static Logger logger = LoggerFactory.getInstance().getLogger(SearchDbServiceAuthCore.class.getName()); + + private static String authFileName = SearchDbConstants.SDB_AUTH_CONFIG_FILENAME; + + private enum HTTP_METHODS { + POST, + GET, + PUT, + DELETE + } + + private static boolean usersInitialized = false; + private static HashMap users; + private static Timer timer = null; + + // Don't instantiate + private SearchDbServiceAuthCore() {} + + public static synchronized void init() { + if (SearchDbServiceAuthCore.authFileName == null) { + SearchDbServiceAuthCore.authFileName = "/home/aaiadmin/etc/aaipolicy.json"; + } + SearchDbServiceAuthCore.reloadUsers(); + } + + public static void cleanup() { + timer.cancel(); + } + + public static synchronized void reloadUsers() { + users = new HashMap<>(); + ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally + JSONParser parser = new JSONParser(); + try { + parser.parse(new FileReader(authFileName)); + JsonNode rootNode = mapper.readTree(new File(authFileName)); + JsonNode rolesNode = rootNode.path("roles"); + + for (JsonNode roleNode : rolesNode) { + String roleName = roleNode.path("name").asText(); + + TabularAuthRole authRole = new TabularAuthRole(); + JsonNode usersNode = roleNode.path("users"); + JsonNode functionsNode = roleNode.path("functions"); + for (JsonNode functionNode : functionsNode) { + String function = functionNode.path("name").asText(); + JsonNode methodsNode = functionNode.path("methods"); + boolean hasMethods = false; + for (JsonNode methodNode : methodsNode) { + String methodName = methodNode.path("name").asText(); + hasMethods = true; + String thisFunction = methodName + ":" + function; + + authRole.addAllowedFunction(thisFunction); + } + + if (!hasMethods) { + // iterate the list from HTTP_METHODS + for (HTTP_METHODS meth : HTTP_METHODS.values()) { + String thisFunction = meth.toString() + ":" + function; + authRole.addAllowedFunction(thisFunction); + } + } + + } + for (JsonNode userNode : usersNode) { + String username = userNode.path("username").asText().toLowerCase(); + SearchDbAuthUser authUser = null; + if (users.containsKey(username)) { + authUser = users.get(username); + } else { + authUser = new SearchDbAuthUser(); + } + + authUser.setUser(username); + authUser.addRole(roleName, authRole); + users.put(username, authUser); + } + } + } catch (FileNotFoundException fnfe) { + logger.debug("Failed to load the policy file "); + + } catch (ParseException e) { + logger.debug("Failed to Parse the policy file "); + + } catch (JsonProcessingException e) { + logger.debug("JSON processing error while parsing policy file: " + e.getMessage()); + + } catch (IOException e) { + logger.debug("IO Exception while parsing policy file: " + e.getMessage()); + } + + usersInitialized = true; + } + + public static class SearchDbAuthUser { + public SearchDbAuthUser() { + this.roles = new HashMap<>(); + } + + private String username; + private HashMap roles; + + public String getUser() { + return this.username; + } + + public Map getRoles() { + return this.roles; + } + + public void addRole(String roleName, TabularAuthRole authRole) { + this.roles.put(roleName, authRole); + } + + public boolean checkAllowed(String checkFunc) { + for (Map.Entry roleEntry : this.roles.entrySet()) { + TabularAuthRole role = roleEntry.getValue(); + if (role.hasAllowedFunction(checkFunc)) { + return true; + } + } + return false; + } + + public void setUser(String myuser) { + this.username = myuser; + } + } + + public static class TabularAuthRole { + public TabularAuthRole() { + this.allowedFunctions = new ArrayList<>(); + } + + private List allowedFunctions; + + public void addAllowedFunction(String func) { + this.allowedFunctions.add(func); + } + + public void delAllowedFunction(String delFunc) { + if (this.allowedFunctions.contains(delFunc)) { + this.allowedFunctions.remove(delFunc); + } + } + + public boolean hasAllowedFunction(String afunc) { + return this.allowedFunctions.contains(afunc); + } + } + + public static Map getUsers() { + if (!usersInitialized || (users == null)) { + reloadUsers(); + } + return users; + } + + public static boolean authorize(String username, String authFunction) { + if (!usersInitialized || (users == null)) { + init(); + } + if (users.containsKey(username)) { + return users.get(username).checkAllowed(authFunction); + } else { + return false; + } + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java new file mode 100644 index 0000000..0b8947e --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java @@ -0,0 +1,229 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; + +/** + * This class encapsulates the configuration of the predefined Analyzer and Filter behaviours that help to tell the + * document store how to index the documents that are provided to it. + */ +public class AnalysisConfiguration { + + /** + * Contains all of the predefined indexing filters. + */ + private FilterSchema[] customFilters; + + /** + * Contains all of the predefined indexing analyzers. + */ + private AnalyzerSchema[] customAnalysers; + + /** + * Indicates whether or not we have imported the filter and analyzer configurations. + */ + private AtomicBoolean configured = new AtomicBoolean(false); + + /** + * A json format string which is readable by Elastic Search and defines all of the custom filters and analyzers that + * we need Elastic Search to know about. + */ + private String esSettings = null; + + private static Logger logger = LoggerFactory.getInstance().getLogger(AnalysisConfiguration.class.getName()); + + + /** + * Imports the filter and analyzer configuration files and builds an Elastic Search readable settings file from the + * contents. + * + * @param filterConfigFile - Location of filter configuration json file + * @param analyzerConfigFile - Location of analyzer configuration json file + */ + public void init(String filterConfigFile, String analyzerConfigFile) { + + if (configured.compareAndSet(false, true)) { + ObjectMapper mapper = new ObjectMapper(); + + File filtersConfig = new File(filterConfigFile); + try { + customFilters = mapper.readValue(filtersConfig, FilterSchema[].class); + } catch (IOException e) { + + // generate log + logger.warn(SearchDbMsgs.FILTERS_CONFIG_FAILURE, filterConfigFile, e.getMessage()); + } + + File analysersConfig = new File(analyzerConfigFile); + try { + customAnalysers = mapper.readValue(analysersConfig, AnalyzerSchema[].class); + } catch (IOException e) { + + // generate log + logger.warn(SearchDbMsgs.ANALYSYS_CONFIG_FAILURE, analyzerConfigFile, e.getMessage()); + } + + esSettings = buildEsIndexSettings(); + } + } + + + /** + * Returns the set of pre-configured filters. + * + * @return - An array of filters. + */ + public FilterSchema[] getFilters() { + return customFilters; + } + + + /** + * Returns the set of pre-configured analyzers. + * + * @return - An array of analyzers. + */ + public AnalyzerSchema[] getAnalyzers() { + init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE); + return customAnalysers; + } + + + /** + * Imports the filter and analyzer configurations and translates those into a settings string that will be parseable + * by Elastic Search. + * + * @return - Elastic Search formatted settings string. + */ + public String getEsIndexSettings() { + + // Generate the es-settings string from our filter and analyzer + // configurations if we have not already done so. + init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE); + + // Now, return the es-settings string. + return esSettings; + } + + + /** + * Constructs a settings string that is readable by Elastic Search based on the contents of the filter and analyzer + * configuration files. + * + * @return Elastic Search formatted settings string. + */ + public String buildEsIndexSettings() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + sb.append("\"analysis\": {"); + + // Define the custom filters. + boolean atLeastOneFilter = false; + sb.append("\"filter\": {"); + AtomicBoolean firstFilter = new AtomicBoolean(true); + for (FilterSchema filter : customFilters) { + + // Append a comma before the next entry, unless it is the + // first one. + if (!firstFilter.compareAndSet(true, false)) { + sb.append(", "); + } + + // Now, build the filter entry. + buildFilterEntry(filter, sb); + atLeastOneFilter = true; + } + sb.append((atLeastOneFilter) ? "}," : "}"); + + // Define the custom analyzers. + sb.append("\"analyzer\": {"); + AtomicBoolean firstAnalyzer = new AtomicBoolean(true); + for (AnalyzerSchema analyzer : customAnalysers) { + + // Prepend a comma before the entry, unless it is the + // first one. + if (!firstAnalyzer.compareAndSet(true, false)) { + sb.append(","); + } + + // Now, construct the entry for this analyzer. + buildAnalyzerEntry(analyzer, sb); + } + sb.append("}"); + + sb.append("}"); + sb.append("}"); + + return sb.toString(); + } + + + /** + * Constructs an ElasticSearch friendly custom filter definition. + * + * @param filter - The filter to generate ElasticSearch json for. + * @param sb - The string builder to append the filter definition to. + */ + private void buildFilterEntry(FilterSchema filter, StringBuilder sb) { + + sb.append("\"" + filter.getName()).append("\": {"); + + sb.append(filter.getConfiguration()); + + sb.append("}"); + } + + + /** + * Constructs an ElasticSearch friendly custom analyzer definition. + * + * @param analyzer - The analyzer to generate ElasticSearch json for. + * @param sb - The string builder to append the analyzer definition to. + */ + private void buildAnalyzerEntry(AnalyzerSchema analyzer, StringBuilder sb) { + + sb.append("\"").append(analyzer.getName()).append("\": {"); + sb.append("\"type\": \"custom\","); + sb.append("\"tokenizer\": ").append("\"").append(analyzer.getTokenizer()).append("\","); + sb.append("\"filter\": ["); + boolean firstFilter = true; + for (String filter : analyzer.getFilters()) { + if (!firstFilter) { + sb.append(","); + } else { + firstFilter = false; + } + sb.append("\"").append(filter).append("\""); + } + sb.append("]"); + sb.append("}"); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java new file mode 100644 index 0000000..3971920 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java @@ -0,0 +1,161 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import java.util.concurrent.atomic.AtomicBoolean; +import javax.servlet.http.HttpServletRequest; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@Component +@EnableWebSecurity +@RestController +@RequestMapping("/services/search-data-service/v1/analyzers/search") +public class AnalyzerApi { + + private SearchServiceApi searchService = null; + + // Set up the loggers. + private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(IndexApi.class.getName()); + + private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; + + public AnalyzerApi(@Qualifier("searchServiceApi") SearchServiceApi searchService) { + this.searchService = searchService; + } + + @RequestMapping(method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"}) + public ResponseEntity processGet(HttpServletRequest request, @RequestHeader HttpHeaders headers, + ApiUtils apiUtils) { + + HttpStatus responseCode = HttpStatus.INTERNAL_SERVER_ERROR; + String responseString; + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + // Validate that the request is correctly authenticated before going + // any further. + try { + + if (!searchService.validateRequest(headers, request, ApiUtils.Action.GET, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, MSG_AUTHENTICATION_FAILURE); + return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) + .body(MSG_AUTHENTICATION_FAILURE); + } + + } catch (Exception e) { + + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, + "Unexpected authentication failure - cause: " + e.getMessage()); + return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) + .body(MSG_AUTHENTICATION_FAILURE); + } + + + // Now, build the list of analyzers. + try { + responseString = buildAnalyzerList(ElasticSearchHttpController.getInstance().getAnalysisConfig()); + responseCode = HttpStatus.OK; + } catch (Exception e) { + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, + "Unexpected failure retrieving analysis configuration - cause: " + e.getMessage()); + responseString = "Failed to retrieve analysis configuration. Cause: " + e.getMessage(); + } + + // Build the HTTP response. + ResponseEntity response = + ResponseEntity.status(responseCode).contentType(MediaType.APPLICATION_JSON).body(responseString); + + // Generate our audit log. + String unknownLogField = "Unknown"; + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, responseCode.value()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, responseCode.value()), + (request != null) ? request.getMethod() : unknownLogField, + (request != null) ? request.getRequestURL().toString() : unknownLogField, + (request != null) ? request.getRemoteHost() : unknownLogField, + Integer.toString(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } + + /** + * This method takes a list of analyzer objects and generates a simple json structure to enumerate them. + * + *

+ * Note, this includes only the aspects of the analyzer object that we want to make public to an external client. + * + * @param analysisConfig - The analysis configuration object to extract the analyzers from. + * @return - A json string enumerating the defined analyzers. + */ + private String buildAnalyzerList(AnalysisConfiguration analysisConfig) { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + AtomicBoolean firstAnalyzer = new AtomicBoolean(true); + for (AnalyzerSchema analyzer : analysisConfig.getAnalyzers()) { + + if (!firstAnalyzer.compareAndSet(true, false)) { + sb.append(", "); + } + + sb.append("{"); + sb.append("\"name\": \"").append(analyzer.getName()).append("\", "); + sb.append("\"description\": \"").append(analyzer.getDescription()).append("\", "); + sb.append("\"behaviours\": ["); + AtomicBoolean firstBehaviour = new AtomicBoolean(true); + for (String behaviour : analyzer.getBehaviours()) { + if (!firstBehaviour.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append("\"").append(behaviour).append("\""); + } + sb.append("]"); + sb.append("}"); + } + sb.append("}"); + + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/ApiUtils.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/ApiUtils.java new file mode 100644 index 0000000..db2fb93 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/ApiUtils.java @@ -0,0 +1,153 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.google.common.base.Strings; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Response.Status.Family; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; +import org.slf4j.MDC; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +/** + * Spring Imports. + * + */ +public class ApiUtils { + + public static final String URL_PREFIX = "services/search-data-service/v1/search"; + public static final String SEARCH_AUTH_POLICY_NAME = "search"; + + private static final String URI_SEGMENT_INDEXES = "indexes"; + private static final String URI_SEGMENT_DOCUMENTS = "documents"; + + public enum Action { + POST, + GET, + PUT, + DELETE + } + + /** + * This method uses the contents of the supplied HTTP headers and request structures to populate the MDC Context + * used for logging purposes. + * + * @param httpReq - HTTP request structure. + * @param headers - HTTP headers + */ + protected static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { + // Auto generate a transaction if we were not provided one. + String transId = null; + if (headers != null) { + transId = headers.getFirst("X-TransactionId"); + if (Strings.isNullOrEmpty(transId)) { + transId = UUID.randomUUID().toString(); + } + } + + String fromIp = (httpReq != null) ? httpReq.getRemoteHost() : ""; + String fromApp = (headers != null) ? headers.getFirst("X-FromAppId") : ""; + + MdcContext.initialize(transId, SearchDbConstants.SDB_SERVICE_NAME, "", fromApp, fromIp); + } + + protected static void clearMdcContext() { + MDC.clear(); + } + + public static String buildIndexUri(String index) { + return (URL_PREFIX + "/indexes/") + index; + } + + public static String buildDocumentUri(String index, String documentId) { + return buildIndexUri(index) + "/documents/" + documentId; + } + + public static boolean validateIndexUri(String uri) { + uri = uri.startsWith("/") ? uri.substring(1) : uri; + String[] tokens = uri.split("/"); + return (tokens.length == 6) && (tokens[4].equals(URI_SEGMENT_INDEXES)); + } + + public static boolean validateDocumentUri(String uri, boolean requireId) { + uri = uri.startsWith("/") ? uri.substring(1) : uri; + String[] tokens = uri.split("/"); + + if (requireId) { + return (tokens.length == 8) + && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); + } else { + return ((tokens.length == 8) || (tokens.length == 7)) + && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); + } + } + + public static String extractIndexFromUri(String uri) { + uri = uri.startsWith("/") ? uri.substring(1) : uri; + + String[] tokens = uri.split("/"); + + int i = 0; + for (String token : tokens) { + if (token.equals(URI_SEGMENT_INDEXES) && i + 1 < tokens.length) { + return tokens[i + 1]; + } + i++; + } + + return null; + } + + public static String extractIdFromUri(String uri) { + uri = uri.startsWith("/") ? uri.substring(1) : uri; + + String[] tokens = uri.split("/"); + + int i = 0; + for (String token : tokens) { + if (token.equals(URI_SEGMENT_DOCUMENTS) && i + 1 < tokens.length) { + return tokens[i + 1]; + } + i++; + } + + return null; + } + + public static String getHttpStatusString(int httpStatusCode) { + try { + return HttpStatus.valueOf(httpStatusCode).getReasonPhrase(); + } catch (IllegalArgumentException e) { + if (207 == httpStatusCode) { + return "Multi-Status"; + } else { + return "Unknown"; + } + } + } + + public static boolean isSuccessStatusCode(int statusCode) { + return Family.familyOf(statusCode).equals(Family.SUCCESSFUL); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkApi.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkApi.java new file mode 100644 index 0000000..810f718 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkApi.java @@ -0,0 +1,209 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.fge.jsonschema.main.JsonSchema; +import com.github.fge.jsonschema.main.JsonSchemaFactory; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.servlet.http.HttpServletRequest; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +/** + * This class encapsulates the REST end points associated with performing bulk operations against the document store. + */ +public class BulkApi { + + /** + * Indicates whether or not we have performed the one-time static initialization required for performing schema + * validation. + */ + protected static AtomicBoolean validationInitialized = new AtomicBoolean(false); + + /** + * Factory used for importing our payload schema for validation purposes. + */ + protected static JsonSchemaFactory schemaFactory = null; + + /** + * Imported payload schema that will be used by our validation methods. + */ + protected static JsonSchema schema = null; + + protected SearchServiceApi searchService = null; + + // Instantiate the loggers. + private static Logger logger = LoggerFactory.getInstance().getLogger(BulkApi.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(BulkApi.class.getName()); + + private static final String MSG_STACK_TRACE = "Stack Trace:\n"; + + /** + * Create a new instance of the BulkApi end point. + */ + public BulkApi(SearchServiceApi searchService) { + this.searchService = searchService; + } + + + /** + * Processes client requests containing a set of operations to be performed in bulk. + * + *

+ * Method: POST + * + * @param operations - JSON structure enumerating the operations to be performed. + * @param request - Raw HTTP request. + * @param headers - HTTP headers. + * @return - A standard REST response structure. + */ + public ResponseEntity processPost(String operations, HttpServletRequest request, HttpHeaders headers, + DocumentStoreInterface documentStore) { + ApiUtils.initMdcContext(request, headers); + + if (logger.isDebugEnabled()) { + logger.debug("SEARCH: Process Bulk Request - operations = [" + operations.replaceAll("\n", "") + " ]"); + } + + // We expect a payload containing a JSON structure enumerating the operations to be performed. + if (operations == null) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); + return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Missing payload", request); + } + + try { + // Validate that the request is correctly authenticated before going any further. + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Authentication failure."); + + return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure.", request); + } + } catch (Exception e) { + // This is a catch all for any unexpected failure trying to perform the authentication. + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, + "Unexpected authentication failure - cause: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + + return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure - cause " + e.getMessage(), + request); + } + + // Marshal the supplied json string into a Java object. + ObjectMapper mapper = new ObjectMapper(); + BulkRequest[] requests = null; + try { + requests = mapper.readValue(operations, BulkRequest[].class); + } catch (IOException e) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Failed to marshal operations list: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + // Populate the result code and entity string for our HTTP response + // and return the response to the client.. + return buildResponse(HttpStatus.BAD_REQUEST.value(), "Unable to marshal operations: " + e.getMessage(), + request); + } + + // Verify that our parsed operations list actually contains some valid operations. + if (requests.length == 0) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Empty operations list in bulk request"); + + // Populate the result code and entity string for our HTTP response + // and return the response to the client.. + return buildResponse(HttpStatus.BAD_REQUEST.value(), "Empty operations list in bulk request", request); + } + + int resultCode; + String resultString; + + try { + // Now, forward the set of bulk operations to the DAO for processing. + OperationResult result = documentStore.performBulkOperations(requests); + + resultCode = result.getResultCode(); + resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); + } catch (DocumentStoreOperationException e) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, + "Unexpected failure communicating with document store: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + + resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); + resultString = "Unexpected failure processing bulk operations: " + e.getMessage(); + } + + ResponseEntity response = + ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + + if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { + logger.info(SearchDbMsgs.PROCESSED_BULK_OPERATIONS); + } else { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, response.getBody()); + } + + return buildResponse(resultCode, resultString, request); + } + + /** + * This method generates an audit log and returns an HTTP response object. + * + * @param resultCode - The result code to report. + * @param resultString - The result string to report. + * @param request - The HTTP request to extract data from for the audit log. + * @return - An HTTP response object. + */ + private ResponseEntity buildResponse(int resultCode, String resultString, HttpServletRequest request) { + ResponseEntity response = + ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + + // Generate our audit log. + String unknownLogField = "Unknown"; + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, ApiUtils.getHttpStatusString(resultCode)), + (request != null) ? request.getMethod() : unknownLogField, + (request != null) ? request.getRequestURL().toString() : unknownLogField, + (request != null) ? request.getRemoteHost() : unknownLogField, + Integer.toString(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java new file mode 100644 index 0000000..7c096a6 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java @@ -0,0 +1,49 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +public class BulkMetaData { + + private String url; + private String etag; + + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getEtag() { + return etag; + } + + public void setEtag(String anEtag) { + this.etag = anEtag; + } + + @Override + public String toString() { + return "MetaData: [url=" + url + ", etag=" + etag + "]"; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkOperation.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkOperation.java new file mode 100644 index 0000000..1490f97 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkOperation.java @@ -0,0 +1,59 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +/** + * This class represents a single instance of an operation to be performed as part of a bulk request. + */ +public class BulkOperation { + + /** + * Contains meta data to be passed to the document store for it to perform the operation. + */ + private BulkMetaData metaData; + + /** + * Contains the contents of the document to be acted on. + */ + private Document document; + + + public void setMetaData(BulkMetaData metaData) { + this.metaData = metaData; + } + + public BulkMetaData getMetaData() { + return metaData; + } + + public Document getDocument() { + return document; + } + + public void setDocument(Document document) { + this.document = document; + } + + @Override + public String toString() { + return "Operation: [" + metaData.toString() + ", " + document + "]"; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkRequest.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkRequest.java new file mode 100644 index 0000000..1f8b50e --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/BulkRequest.java @@ -0,0 +1,110 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + + +/** + * This class represents a single instance of a request from the search client that would be part of a bundle of such + * operations sent in a single bulk request. + */ +public class BulkRequest { + + public enum OperationType { + CREATE, + UPDATE, + DELETE + } + + private BulkOperation create; + private BulkOperation update; + private BulkOperation delete; + + public BulkOperation getCreate() { + return create; + } + + public void setCreate(BulkOperation create) { + this.create = create; + } + + public BulkOperation getUpdate() { + return update; + } + + public void setUpdate(BulkOperation update) { + this.update = update; + } + + public BulkOperation getDelete() { + return delete; + } + + public void setDelete(BulkOperation delete) { + this.delete = delete; + } + + public OperationType getOperationType() { + + if (create != null) { + return OperationType.CREATE; + } else if (update != null) { + return OperationType.UPDATE; + } else if (delete != null) { + return OperationType.DELETE; + } else { + return null; + } + } + + public BulkOperation getOperation() { + if (create != null) { + return create; + } else if (update != null) { + return update; + } else if (delete != null) { + return delete; + } else { + return null; + } + } + + public String getIndex() { + return ApiUtils.extractIndexFromUri(getOperation().getMetaData().getUrl()); + } + + public String getId() { + return ApiUtils.extractIdFromUri(getOperation().getMetaData().getUrl()); + } + + @Override + public String toString() { + + if (create != null) { + return "create: [" + create.toString() + "]\n"; + } else if (update != null) { + return "update: [" + update.toString() + "]\n"; + } else if (delete != null) { + return "delete: [" + delete.toString() + "]\n"; + } else { + return "UNDEFINED"; + } + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/Document.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/Document.java new file mode 100644 index 0000000..e9bcaf4 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/Document.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +public class Document { + private Map fields = new HashMap<>(); + + @JsonAnyGetter + public Map getFields() { + return fields; + } + + @JsonAnySetter + public void setField(String name, Object value) { + fields.put(name, value); + } + + public String toJson() throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Document: ["); + for (Entry entry : fields.entrySet()) { + sb.append(entry.getKey()).append(": ").append(entry.getValue()); + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/DocumentApi.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/DocumentApi.java new file mode 100644 index 0000000..da8be98 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/DocumentApi.java @@ -0,0 +1,599 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntityImpl; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; +import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.onap.aai.sa.searchdbabstraction.searchapi.SearchStatement; +import org.onap.aai.sa.searchdbabstraction.searchapi.SuggestionStatement; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +public class DocumentApi { + private static final String MSG_REQUEST_BODY = "Request Body: "; + private static final String REQUEST_HEADER_RESOURCE_VERSION = "If-Match"; + private static final String RESPONSE_HEADER_RESOURCE_VERSION = "ETag"; + private static final String REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION = "X-CreateIndex"; + + protected SearchServiceApi searchService = null; + + private Logger logger = LoggerFactory.getInstance().getLogger(DocumentApi.class.getName()); + private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(DocumentApi.class.getName()); + + public DocumentApi(SearchServiceApi searchService) { + this.searchService = searchService; + } + + public ResponseEntity processPost(String content, HttpServletRequest request, HttpHeaders headers, + HttpServletResponse httpResponse, String index, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + if (content == null) { + return handleError(request, content, HttpStatus.BAD_REQUEST); + } + + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processPost", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); + document.setContent(content); + + DocumentOperationResult result = + documentStore.createDocument(index, document, implicitlyCreateIndex(headers)); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + + if (httpResponse != null) { + httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); + } + ResponseEntity response = + ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); + logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); + logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public ResponseEntity processPut(String content, HttpServletRequest request, HttpHeaders headers, + HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + if (content == null) { + return handleError(request, content, HttpStatus.BAD_REQUEST); + } + + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.PUT, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processPut", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); + + DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); + document.setId(id); + document.setContent(content); + document.setVersion(resourceVersion); + + DocumentOperationResult result = null; + if (resourceVersion == null) { + result = documentStore.createDocument(index, document, implicitlyCreateIndex(headers)); + } else { + result = documentStore.updateDocument(index, document, implicitlyCreateIndex(headers)); + } + + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + if (httpResponse != null) { + httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); + } + ResponseEntity response = + ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); + logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public ResponseEntity processDelete(String content, HttpServletRequest request, HttpHeaders headers, + HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.DELETE, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processDelete", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); + if (resourceVersion == null || resourceVersion.isEmpty()) { + return handleError(request, "Request header 'If-Match' missing", HttpStatus.BAD_REQUEST); + } + + DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); + document.setId(id); + document.setVersion(resourceVersion); + + DocumentOperationResult result = documentStore.deleteDocument(index, document); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + + if (httpResponse != null) { + httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); + } + ResponseEntity response; + if (output == null) { + response = ResponseEntity.status(result.getResultCode()).build(); + } else { + response = ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) + .body(output); + } + + logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public ResponseEntity processGet(String content, HttpServletRequest request, HttpHeaders headers, + HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.GET, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processGet", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); + + DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); + document.setId(id); + document.setVersion(resourceVersion); + + DocumentOperationResult result = documentStore.getDocument(index, document); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + if (httpResponse != null) { + httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); + } + ResponseEntity response = + ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); + logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public ResponseEntity processSearchWithGet(String content, HttpServletRequest request, HttpHeaders headers, + String index, String queryText, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.GET, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processSearchWithGet", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + SearchOperationResult result = documentStore.search(index, queryText); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSearchResult()); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + ResponseEntity response = + ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + public ResponseEntity queryWithGetWithPayload(String content, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "GET", + (request != null) ? request.getRequestURL().toString() : ""); + if (logger.isDebugEnabled()) { + logger.debug(MSG_REQUEST_BODY + content); + } + return processQuery(index, content, request, headers, documentStore); + } + + public ResponseEntity processSearchWithPost(String content, HttpServletRequest request, HttpHeaders headers, + String index, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", + (request != null) ? request.getRequestURL().toString() : ""); + if (logger.isDebugEnabled()) { + logger.debug(MSG_REQUEST_BODY + content); + } + + return processQuery(index, content, request, headers, documentStore); + } + + + public ResponseEntity processSuggestQueryWithPost(String content, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", + (request != null) ? request.getRequestURL().toString() : ""); + if (logger.isDebugEnabled()) { + logger.debug(MSG_REQUEST_BODY + content); + } + + return processSuggestQuery(index, content, request, headers, documentStore); + } + + /** + * Common handler for query requests. This is called by both the GET with payload and POST with payload variants of + * the query endpoint. + * + * @param index - The index to be queried against. + * @param content - The payload containing the query structure. + * @param request - The HTTP request. + * @param headers - The HTTP headers. + * @return - A standard HTTP response. + */ + private ResponseEntity processQuery(String index, String content, HttpServletRequest request, + HttpHeaders headers, DocumentStoreInterface documentStore) { + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + + // Make sure that we were supplied a payload before proceeding. + if (content == null) { + return handleError(request, content, HttpStatus.BAD_REQUEST); + } + + // Validate that the request has the appropriate authorization. + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processQuery", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + SearchStatement searchStatement; + + try { + // Marshall the supplied request payload into a search statement + // object. + searchStatement = mapper.readValue(content, SearchStatement.class); + + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.BAD_REQUEST); + } + + // Now, submit the search statement, translated into + // ElasticSearch syntax, to the document store DAO. + SearchOperationResult result = documentStore.searchWithPayload(index, searchStatement.toElasticSearch()); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = prepareOutput(mapper, result); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + ResponseEntity response = + ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + + /** + * Common handler for query requests. This is called by both the GET with payload and POST with payload variants of + * the query endpoint. + * + * @param index - The index to be queried against. + * @param content - The payload containing the query structure. + * @param request - The HTTP request. + * @param headers - The HTTP headers. + * @return - A standard HTTP response. + */ + private ResponseEntity processSuggestQuery(String index, String content, HttpServletRequest request, + HttpHeaders headers, DocumentStoreInterface documentStore) { + + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + + // Make sure that we were supplied a payload before proceeding. + if (content == null) { + return handleError(request, content, HttpStatus.BAD_REQUEST); + } + + // Validate that the request has the appropriate authorization. + boolean isValid; + try { + isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME); + + } catch (Exception e) { + logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processQuery", e.getMessage()); + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + if (!isValid) { + return handleError(request, content, HttpStatus.FORBIDDEN); + } + + SuggestionStatement suggestionStatement; + + try { + // Marshall the supplied request payload into a search statement + // object. + suggestionStatement = mapper.readValue(content, SuggestionStatement.class); + + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.BAD_REQUEST); + } + + // Now, submit the search statement, translated into + // ElasticSearch syntax, to the document store DAO. + SearchOperationResult result = + documentStore.suggestionQueryWithPayload(index, suggestionStatement.toElasticSearch()); + String output = null; + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + output = prepareSuggestOutput(mapper, result); + } else { + output = result.getError() != null + ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) + : result.getFailureCause(); + } + ResponseEntity response = ResponseEntity.status(result.getResultCode()).body(output); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + + } catch (Exception e) { + return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * Checks the supplied HTTP headers to see if we should allow the underlying document store to implicitly create the + * index referenced in a document PUT or POST if it does not already exist in the data store. + * + * @param headers - The HTTP headers to examine. + * + * @return - true if the headers indicate that missing indices should be implicitly created, false otherwise. + */ + private boolean implicitlyCreateIndex(HttpHeaders headers) { + String implicitIndexCreationHeader = headers.getFirst(REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION); + return implicitIndexCreationHeader != null && "true".equals(implicitIndexCreationHeader); + } + + private String prepareOutput(ObjectMapper mapper, SearchOperationResult result) throws JsonProcessingException { + StringBuffer output = new StringBuffer(); + output.append("{\r\n\"searchResult\":"); + output.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSearchResult())); + AggregationResults aggs = result.getAggregationResult(); + if (aggs != null) { + output.append(",\r\n\"aggregationResult\":"); + output.append(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() + .writeValueAsString(aggs)); + } + output.append("\r\n}"); + return output.toString(); + } + + private String prepareSuggestOutput(ObjectMapper mapper, SearchOperationResult result) + throws JsonProcessingException { + StringBuffer output = new StringBuffer(); + output.append("{\r\n\"searchResult\":"); + output.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSuggestResult())); + AggregationResults aggs = result.getAggregationResult(); + if (aggs != null) { + output.append(",\r\n\"aggregationResult\":"); + output.append(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() + .writeValueAsString(aggs)); + } + output.append("\r\n}"); + return output.toString(); + } + + private ResponseEntity handleError(HttpServletRequest request, String message, HttpStatus status) { + logResult(request, status); + return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(message); + } + + void logResult(HttpServletRequest request, HttpStatus status) { + + logger.info(SearchDbMsgs.PROCESS_REST_REQUEST, (request != null) ? request.getMethod() : "", + (request != null) ? request.getRequestURL().toString() : "", + (request != null) ? request.getRemoteHost() : "", Integer.toString(status.value())); + + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status.value()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), + (request != null) ? request.getMethod() : "", + (request != null) ? request.getRequestURL().toString() : "", + (request != null) ? request.getRemoteHost() : "", Integer.toString(status.value())); + + // Clear the MDC context so that no other transaction inadvertently uses our transaction id. + ApiUtils.clearMdcContext(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/IndexApi.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/IndexApi.java new file mode 100644 index 0000000..04fbcf3 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/IndexApi.java @@ -0,0 +1,402 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.FileNotFoundException; +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +/** + * This class encapsulates the REST end points associated with manipulating indexes in the document store. + */ +public class IndexApi { + + private static final String UNKNOWN_LOG_FIELD_STR = "Unknown"; + private static final String MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE = + "Unexpected authentication failure - cause: "; + private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; + private static final String HEADER_VALIDATION_SUCCESS = "SUCCESS"; + protected SearchServiceApi searchService = null; + + /** + * Configuration for the custom analyzers that will be used for indexing. + */ + protected AnalysisConfiguration analysisConfig; + + // Set up the loggers. + private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(IndexApi.class.getName()); + + + public IndexApi(SearchServiceApi searchService) { + this.searchService = searchService; + init(); + } + + + /** + * Initializes the end point. + * + * @throws FileNotFoundException + * @throws IOException + * @throws DocumentStoreOperationException + */ + public void init() { + + // Instantiate our analysis configuration object. + analysisConfig = new AnalysisConfiguration(); + } + + + /** + * Processes client requests to create a new index and document type in the document store. + * + * @param documentSchema - The contents of the request body which is expected to be a JSON structure which + * corresponds to the schema defined in document.schema.json + * @param index - The name of the index to create. + * @return - A Standard REST response + */ + public ResponseEntity processCreateIndex(String documentSchema, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { + + int resultCode = 500; + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + // Validate that the request is correctly authenticated before going any further. + try { + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + } catch (Exception e) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, + MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + + // We expect a payload containing the document schema. Make sure + // it is present. + if (documentSchema == null) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Missing document schema payload"); + return errorResponse(HttpStatus.valueOf(resultCode), "Missing payload", request); + } + + String resultString; + + try { + // Marshal the supplied json string into a document schema object. + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); + + // Now, ask the DAO to create the index. + OperationResult result = documentStore.createIndex(index, schema); + + // Extract the result code and string from the OperationResult + // object so that we can use them to generate a standard REST + // response. + // Note that we want to return a 201 result code on a successful + // create, so if we get back a 200 from the document store, + // translate that int a 201. + resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); + resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); + + } catch (com.fasterxml.jackson.core.JsonParseException + | com.fasterxml.jackson.databind.JsonMappingException e) { + + // We were unable to marshal the supplied json string into a valid + // document schema, so return an appropriate error response. + resultCode = HttpStatus.BAD_REQUEST.value(); + resultString = "Malformed schema: " + e.getMessage(); + + } catch (IOException e) { + + // We'll treat this is a general internal error. + resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); + resultString = "IO Failure: " + e.getMessage(); + } + + ResponseEntity response = + ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + + if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { + logger.info(SearchDbMsgs.CREATED_INDEX, index); + } else { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, resultString); + } + + // Generate our audit log. + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode).setField( + LogLine.DefinedFields.RESPONSE_DESCRIPTION, HttpStatus.valueOf(resultCode).toString()), + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, + Integer.toString(response.getStatusCodeValue())); + + + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + // Finally, return the response. + return response; + } + + /** + * This function accepts any JSON and will "blindly" write it to the document store. + * + * Note, eventually this "dynamic" flow should follow the same JSON-Schema validation procedure as the normal create + * index flow. + * + * @param dynamicSchema - The JSON string that will be sent to the document store. + * @param index - The name of the index to be created. + * @param documentStore - The document store specific interface. + * @return The result of the document store interface's operation. + */ + public ResponseEntity processCreateDynamicIndex(String dynamicSchema, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { + + ResponseEntity response = null; + + ResponseEntity validationResponse = + validateRequest(request, headers, index, SearchDbMsgs.INDEX_CREATE_FAILURE); + + + if (validationResponse.getStatusCodeValue() != HttpStatus.OK.value()) { + response = validationResponse; + } else { + OperationResult result = documentStore.createDynamicIndex(index, dynamicSchema); + + int resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); + String resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); + + response = ResponseEntity.status(resultCode).body(resultString); + } + + return response; + } + + /** + * Processes a client request to remove an index from the document store. Note that this implicitly deletes all + * documents contained within that index. + * + * @param index - The index to be deleted. + * @return - A standard REST response. + */ + public ResponseEntity processDelete(String index, HttpServletRequest request, HttpHeaders headers, + DocumentStoreInterface documentStore) { + + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + + ResponseEntity response; + + // Validate that the request is correctly authenticated before going + // any further. + try { + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + } catch (Exception e) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, + MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + try { + // Send the request to the document store. + response = responseFromOperationResult(documentStore.deleteIndex(index)); + } catch (DocumentStoreOperationException e) { + response = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON) + .body(e.getMessage()); + } + + if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { + logger.info(SearchDbMsgs.DELETED_INDEX, index); + } else { + logger.warn(SearchDbMsgs.INDEX_DELETE_FAILURE, index, response.getBody()); + } + + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatusCodeValue()).setField( + LogLine.DefinedFields.RESPONSE_DESCRIPTION, response.getStatusCode().getReasonPhrase()), + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, + Integer.toString(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; + } + + + /** + * This method takes a JSON format document schema and produces a set of field mappings in the form that Elastic + * Search expects. + * + * @param documentSchema - A document schema expressed as a JSON string. + * @return - A JSON string expressing an Elastic Search mapping configuration. + * @throws com.fasterxml.jackson.core.JsonParseException + * @throws com.fasterxml.jackson.databind.JsonMappingException + * @throws IOException + */ + public String generateDocumentMappings(String documentSchema) throws IOException { + + // Unmarshal the json content into a document schema object. + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); + + // Now, generate the Elastic Search mapping json and return it. + StringBuilder sb = new StringBuilder(); + sb.append("{"); + sb.append("\"properties\": {"); + + boolean first = true; + for (DocumentFieldSchema field : schema.getFields()) { + + if (!first) { + sb.append(","); + } else { + first = false; + } + + sb.append("\"").append(field.getName()).append("\": {"); + + // The field type is mandatory. + sb.append("\"type\": \"").append(field.getDataType()).append("\""); + + // If the index field was specified, then append it. + if (field.getSearchable() != null) { + sb.append(", \"index\": \"").append(field.getSearchable() ? "analyzed" : "not_analyzed").append("\""); + } + + // If a search analyzer was specified, then append it. + if (field.getSearchAnalyzer() != null) { + sb.append(", \"search_analyzer\": \"").append(field.getSearchAnalyzer()).append("\""); + } + + // If an indexing analyzer was specified, then append it. + if (field.getIndexAnalyzer() != null) { + sb.append(", \"analyzer\": \"").append(field.getIndexAnalyzer()).append("\""); + } else { + sb.append(", \"analyzer\": \"").append("whitespace").append("\""); + } + + sb.append("}"); + } + + sb.append("}"); + sb.append("}"); + + logger.debug("Generated document mappings: " + sb.toString()); + + return sb.toString(); + } + + + /** + * Converts an {@link OperationResult} to a standard REST {@link ResponseEntity} object. + * + * @param result - The {@link OperationResult} to be converted. + * @return - The equivalent {@link ResponseEntity} object. + */ + public ResponseEntity responseFromOperationResult(OperationResult result) { + + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { + return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) + .body(result.getResult()); + } else { + if (result.getFailureCause() != null) { + return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) + .body(result.getFailureCause()); + } else { + return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) + .body(result.getResult()); + } + } + } + + public ResponseEntity errorResponse(HttpStatus status, String msg, HttpServletRequest request) { + + // Generate our audit log. + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status.value()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, Integer.toString(status.value())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(msg); + } + + + /** + * A helper method used for validating/authenticating an incoming request. + * + * @param request - The http request that will be validated. + * @param headers - The http headers that will be validated. + * @param index - The name of the index that the document store request is being made against. + * @param failureMsgEnum - The logging message to be used upon validation failure. + * @return A success or failure response + */ + private ResponseEntity validateRequest(HttpServletRequest request, HttpHeaders headers, String index, + SearchDbMsgs failureMsgEnum) { + try { + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(failureMsgEnum, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + } catch (Exception e) { + logger.warn(failureMsgEnum, index, MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + return ResponseEntity.status(HttpStatus.OK).body(HEADER_VALIDATION_SUCCESS); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java new file mode 100644 index 0000000..d62bfd6 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java @@ -0,0 +1,216 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import java.security.cert.X509Certificate; +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.onap.aai.sa.auth.SearchDbServiceAuth; +import org.onap.aai.sa.rest.ApiUtils.Action; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@Component +@EnableWebSecurity +@RestController +@RequestMapping("/services/search-data-service/v1/search") +public class SearchServiceApi { + + /** + * The Data Access Object that we will use to interact with the document store. + */ + protected DocumentStoreInterface documentStore = null; + protected ApiUtils apiUtils = null; + + /** + * Create a new instance of the end point. + */ + public SearchServiceApi() { + + // Perform one-time initialization. + init(); + } + + + /** + * Performs all one-time initialization required for the end point. + */ + public void init() { + // Instantiate our Document Store DAO. + documentStore = ElasticSearchHttpController.getInstance(); + } + + @RequestMapping(value = "/indexes/{index}", method = RequestMethod.PUT, produces = {"application/json"}) + public ResponseEntity processCreateIndex(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + // Forward the request to our index API to create the index. + IndexApi indexApi = new IndexApi(this); + return indexApi.processCreateIndex(requestBody, request, headers, index, documentStore); + } + + @RequestMapping(value = "/indexes/{index}", method = RequestMethod.DELETE, consumes = {"application/json"}, + produces = {"application/json"}) + public ResponseEntity processDeleteIndex(HttpServletRequest request, @RequestHeader HttpHeaders headers, + @PathVariable("index") String index) { + + // Forward the request to our index API to delete the index. + IndexApi indexApi = new IndexApi(this); + return indexApi.processDelete(index, request, headers, documentStore); + } + + + @RequestMapping(value = "/indexes/{index}/documents", method = RequestMethod.POST, consumes = {"application/json"}) + public ResponseEntity processCreateDocWithoutId(@RequestBody String requestBody, HttpServletRequest request, + HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + // Forward the request to our document API to create the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processPost(requestBody, request, headers, httpResponse, index, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.PUT, + consumes = {"application/json"}) + public ResponseEntity processUpsertDoc(@RequestBody String requestBody, HttpServletRequest request, + HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index, + @PathVariable("id") String id) { + + // Forward the request to our document API to upsert the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processPut(requestBody, request, headers, httpResponse, index, id, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.GET) + public ResponseEntity processGetDocument(HttpServletRequest request, HttpServletResponse httpResponse, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { + + // Forward the request to our document API to retrieve the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processGet("", request, headers, httpResponse, index, id, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.DELETE, + consumes = {"application/json"}) + public ResponseEntity processDeleteDoc(HttpServletRequest request, HttpServletResponse httpResponse, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { + + // Forward the request to our document API to delete the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processDelete("", request, headers, httpResponse, index, id, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/query/{queryText}", method = RequestMethod.GET) + public ResponseEntity processInlineQuery(HttpServletRequest request, @RequestHeader HttpHeaders headers, + @PathVariable("index") String index, @PathVariable("queryText") String queryText) { + + // Forward the request to our document API to delete the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processSearchWithGet("", request, headers, index, queryText, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.GET, consumes = {"application/json"}) + public ResponseEntity processQueryWithGet(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + // Forward the request to our document API to delete the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.queryWithGetWithPayload(requestBody, request, headers, index, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.POST, consumes = {"application/json"}) + public ResponseEntity processQuery(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + // Forward the request to our document API to delete the document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processSearchWithPost(requestBody, request, headers, index, documentStore); + } + + @RequestMapping(value = "/indexes/{index}/suggest", method = RequestMethod.POST, consumes = {"application/json"}) + public ResponseEntity processSuggestQuery(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + // Forward the request to our document API to query suggestions in the + // document. + DocumentApi documentApi = new DocumentApi(this); + return documentApi.processSuggestQueryWithPost(requestBody, request, headers, index, documentStore); + } + + @RequestMapping(value = "/indexes/dynamic/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) + public ResponseEntity processCreateDynamicIndex(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + // Forward the request to our index API to create the index. + IndexApi indexApi = new IndexApi(this); + return indexApi.processCreateDynamicIndex(requestBody, request, headers, index, documentStore); + } + + @RequestMapping(value = "/bulk", method = RequestMethod.POST, consumes = {"application/json"}, + produces = {"application/json"}) + public ResponseEntity processBulkRequest(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers) { + + // Forward the request to our document API to delete the document. + BulkApi bulkApi = new BulkApi(this); + return bulkApi.processPost(requestBody, request, headers, documentStore); + } + + protected boolean validateRequest(HttpHeaders headers, HttpServletRequest req, Action action, + String authPolicyFunctionName) { + + boolean isUserAuthEnabled = ((ElasticSearchHttpController)documentStore).getElasticSearchConfig().useAuthorizationUser(); + if(! isUserAuthEnabled) { + return true; + } + + SearchDbServiceAuth serviceAuth = new SearchDbServiceAuth(); + + String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); + String authUser = null; + if (cipherSuite != null) { + Object x509CertAttribute = req.getAttribute("javax.servlet.request.X509Certificate"); + if (x509CertAttribute != null) { + X509Certificate[] certChain = (X509Certificate[]) x509CertAttribute; + X509Certificate clientCert = certChain[0]; + X500Principal subjectDn = clientCert.getSubjectX500Principal(); + authUser = subjectDn.toString(); + } + } + + if (authUser == null) { + return false; + } + + String status = + serviceAuth.authUser(headers, authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); + return status.equals("OK"); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java b/search-data-service/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java new file mode 100644 index 0000000..74e46f4 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java @@ -0,0 +1,84 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 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========================================================= + */ +package org.onap.aai.sa.rest; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.atomic.AtomicBoolean; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; + + +public class SettingConfiguration { + + /** + * Indicates whether or not we have imported the filter and analyzer configurations. + */ + private AtomicBoolean configured = new AtomicBoolean(false); + + /** + * A json format string which is readable by Elastic Search and defines all of the custom filters and analyzers that + * we need Elastic Search to know about. + */ + private String settings; + + public void init(String settingConfigFile) { + + if (configured.compareAndSet(false, true)) { + try { + Path path = Paths.get(settingConfigFile); + settings = new String(Files.readAllBytes(path)); + + // Remove the enclosing brackets from the json blob. + settings = settings.replaceFirst("\\{", ""); + settings = settings.substring(0, settings.lastIndexOf("}")); + } catch (IOException e) { + // It is valid not to have a settings file. + settings = ""; + } + } + } + + + /** + * Returns the set of pre-configured settings. + * + * @return - settings. + */ + public String getSettings() { + init(SearchDbConstants.SDB_SETTINGS_CONFIG_FILE); + return settings; + } + + public String getSettingsWithAnalysis(AnalysisConfiguration analysisConfig) { + String ac = analysisConfig.getEsIndexSettings(); + StringBuilder sb = new StringBuilder(); + sb.append(ac.substring(0, ac.lastIndexOf("}"))); + + if (!getSettings().trim().isEmpty()) { + sb.append(", " + getSettings()); + } + + sb.append(" }"); + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java new file mode 100644 index 0000000..96929c7 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java @@ -0,0 +1,47 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ + +package org.onap.aai.sa.searchdbabstraction; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * Exposes REST endpoints for a simple echo service. + */ +@RestController +@RequestMapping("/services/search-data-service/v1") +public class RestEchoService { + + /** + * REST endpoint for a simple echo service. + * + * @param input - The value to be echoed back. + * @return - The input value. + */ + @RequestMapping(value = "/echo/{input}", method = {RequestMethod.GET}) + public String ping(@PathVariable("input") String input) { + return "[Search Database Abstraction Micro Service] - Echo Service: " + input + "."; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java new file mode 100644 index 0000000..4680ded --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java @@ -0,0 +1,240 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.config; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Optional; +import java.util.Properties; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; + +public class ElasticSearchConfig { + + private String uriScheme; + private String trustStore; + private String trustStorePassword; + private String keyStore; + private String keyStorePassword; + private String authUser; + private String authPassword; + private String ipAddress; + private String httpPort; + private String javaApiPort; + private String clusterName; + private String authorizationEnabled; + + public static final String ES_CLUSTER_NAME = "es.cluster-name"; + public static final String ES_IP_ADDRESS = "es.ip-address"; + public static final String ES_HTTP_PORT = "es.http-port"; + public static final String ES_URI_SCHEME = "es.uri-scheme"; + public static final String ES_TRUST_STORE = "es.trust-store"; + public static final String ES_TRUST_STORE_ENC = "es.trust-store-password"; + public static final String ES_KEY_STORE = "es.key-store"; + public static final String ES_KEY_STORE_ENC = "es.key-store-password"; + public static final String ES_AUTH_USER = "es.auth-user"; + public static final String ES_AUTH_ENC = "es.auth-password"; + public static final String ES_AUTH_ENABLED = "es.auth.authorization.enabled"; + + private static final String DEFAULT_URI_SCHEME = "http"; + private static final String JAVA_API_PORT_DEFAULT = "9300"; + private String authValue; + + public ElasticSearchConfig(Properties props) { + setUriScheme(props.getProperty(ES_URI_SCHEME)); + if (getUriScheme().equals("https")) { + initializeHttpsProperties(props); + } + setClusterName(props.getProperty(ES_CLUSTER_NAME)); + setIpAddress(props.getProperty(ES_IP_ADDRESS)); + setHttpPort(props.getProperty(ES_HTTP_PORT)); + setJavaApiPort(JAVA_API_PORT_DEFAULT); + initializeAuthValues(props); + setAuthorizationEnabled(props.getProperty(ES_AUTH_ENABLED)); + } + + + public String getUriScheme() { + return this.uriScheme; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getHttpPort() { + return httpPort; + } + + public void setHttpPort(String httpPort) { + this.httpPort = httpPort; + } + + public String getJavaApiPort() { + return javaApiPort; + } + + public void setJavaApiPort(String javaApiPort) { + this.javaApiPort = javaApiPort; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public String getKeyStorePath() { + return keyStore; + } + + public String getKeyStorePassword() { + return keyStorePassword; + } + + public String getTrustStorePath() { + return trustStore; + } + + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + public String getTrustStorePassword() { + return trustStorePassword; + } + + public void setAuthUser(String authUser) { + this.authUser = authUser; + } + + public String getAuthUser() { + return authUser; + } + + public void setAuthPassword(String authPassword) { + this.authPassword = authPassword; + } + + public String getAuthPassword() { + return authPassword; + } + + public boolean useAuth() { + return getAuthUser() != null || getAuthPassword() != null; + } + + public String getAuthValue() { + return authValue; + } + + public String getAuthorizationEnabled() { + return authorizationEnabled; + } + + public void setAuthorizationEnabled(String authorizationEnabled) { + this.authorizationEnabled = authorizationEnabled; + } + + public boolean useAuthorizationUser() { + return getAuthorizationEnabled()== null? true : Boolean.parseBoolean(getAuthorizationEnabled()); + } + + @Override + public String toString() { + return String.format( + "%s://%s:%s (cluster=%s) (API port=%s)%nauth=%s%ntrustStore=%s (passwd %s)%nkeyStore=%s (passwd %s)%nauthorizationUser=%s", + uriScheme, ipAddress, httpPort, clusterName, javaApiPort, useAuth(), trustStore, + trustStorePassword != null, keyStore, keyStorePassword != null, useAuthorizationUser()); + } + + private void initializeAuthValues(Properties props) { + setAuthUser(props.getProperty(ES_AUTH_USER)); + Optional passwordValue = Optional.ofNullable(props.getProperty(ES_AUTH_ENC)); + if (passwordValue.isPresent()) { + setAuthPassword(Password.deobfuscate(passwordValue.get())); + } + if (useAuth()) { + authValue = "Basic " + Base64.getEncoder() + .encodeToString((getAuthUser() + ":" + getAuthPassword()).getBytes(StandardCharsets.UTF_8)); + } + } + + private void initializeHttpsProperties(Properties props) { + Optional trustStoreFile = Optional.ofNullable(props.getProperty(ES_TRUST_STORE)); + if (trustStoreFile.isPresent()) { + setTrustStore(SearchDbConstants.SDB_SPECIFIC_CONFIG + trustStoreFile.get()); + } + + Optional passwordValue = Optional.ofNullable(props.getProperty(ES_TRUST_STORE_ENC)); + if (passwordValue.isPresent()) { + if(passwordValue.get().startsWith("OBF:")){ + setTrustStorePassword(Password.deobfuscate(passwordValue.get())); + }else if(passwordValue.get().startsWith("ENV:")){ + setTrustStorePassword(System.getenv(StringUtils.removeStart(passwordValue.get(), "ENV:"))); + } + else{ + setTrustStorePassword(passwordValue.get()); + } + } + + Optional keyStoreFile = Optional.ofNullable(props.getProperty(ES_KEY_STORE)); + if (keyStoreFile.isPresent()) { + setKeyStore(SearchDbConstants.SDB_SPECIFIC_CONFIG + keyStoreFile.get()); + } + + passwordValue = Optional.ofNullable(props.getProperty(ES_KEY_STORE_ENC)); + if (passwordValue.isPresent()) { + if(passwordValue.get().startsWith("OBF:")){ + setKeyStorePassword(Password.deobfuscate(passwordValue.get())); + }else if(passwordValue.get().startsWith("ENV:")){ + setKeyStorePassword(System.getenv(StringUtils.removeStart(passwordValue.get(), "ENV:"))); + } + else{ + setKeyStorePassword(passwordValue.get()); + } + } + } + + private void setUriScheme(String uriScheme) { + this.uriScheme = Optional.ofNullable(uriScheme).orElse(DEFAULT_URI_SCHEME); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java new file mode 100644 index 0000000..3d95a1b --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java @@ -0,0 +1,31 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +public interface DocumentStoreDataEntity { + + public String getId(); + + public String getContentInJson(); + + public String getVersion(); + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java new file mode 100644 index 0000000..413dbb4 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java @@ -0,0 +1,60 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +public class DocumentStoreDataEntityImpl implements DocumentStoreDataEntity { + + private String id; + private String content; + private String version; + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public void setId(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getContentInJson() { + return content; + } + + @Override + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java new file mode 100644 index 0000000..5ea37e1 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + + +import org.onap.aai.sa.rest.BulkRequest; +import org.onap.aai.sa.rest.DocumentSchema; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; + + +public interface DocumentStoreInterface { + + public OperationResult createIndex(String index, DocumentSchema documentSchema); + + public OperationResult createDynamicIndex(String index, String dynamicSchema); + + public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException; + + public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException; + + public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException; + + public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) + throws DocumentStoreOperationException; + + public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException; + + public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException; + + public SearchOperationResult search(String indexName, String queryText) throws DocumentStoreOperationException; + + public SearchOperationResult searchWithPayload(String indexName, String query) + throws DocumentStoreOperationException; + + + /** + * Forwards a set of operations to the document store as a single, bulk request. + * + * @param anIndex - The index to apply the operations to. + * @param operations - A java object containing the set of operations to be performed. + * @return - An operation result. + * @throws DocumentStoreOperationException + */ + public OperationResult performBulkOperations(BulkRequest[] request) throws DocumentStoreOperationException; +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java new file mode 100644 index 0000000..23181df --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import java.util.Arrays; + +public class ElasticSearchBulkOperationResult { + + private Integer took; + private Boolean errors; + private ElasticSearchResultItem[] items; + + public ElasticSearchBulkOperationResult() { + + } + + public ElasticSearchResultItem[] getItems() { + return items; + } + + public void setItems(ElasticSearchResultItem[] items) { + this.items = items; + } + + public Integer getTook() { + return took; + } + + public void setTook(Integer took) { + this.took = took; + } + + public Boolean getErrors() { + return errors; + } + + public void setErrors(Boolean errors) { + this.errors = errors; + } + + @Override + public String toString() { + return "ElasticSearchOperationResult [took=" + took + ", errors=" + errors + ", items=" + Arrays.toString(items) + + "]"; + } + + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java new file mode 100644 index 0000000..ee12494 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +public class ElasticSearchCause { + + private String type; + private String reason; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java new file mode 100644 index 0000000..1880168 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import java.util.HashMap; +import java.util.Map; + +public class ElasticSearchError { + + private String type; + private String reason; + private ElasticSearchCause causedBy; + + private Map additionalProperties = new HashMap<>(); + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public ElasticSearchCause getCausedBy() { + return causedBy; + } + + public void setCausedBy(ElasticSearchCause causedBy) { + this.causedBy = causedBy; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperties(String name, Object value) { + additionalProperties.put(name, value); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java new file mode 100644 index 0000000..a4af160 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java @@ -0,0 +1,1410 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ + +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Throwables; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import org.eclipse.jetty.http.HttpStatus; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +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.cl.mdc.MdcOverride; +import org.onap.aai.sa.rest.AnalysisConfiguration; +import org.onap.aai.sa.rest.ApiUtils; +import org.onap.aai.sa.rest.BulkRequest; +import org.onap.aai.sa.rest.BulkRequest.OperationType; +import org.onap.aai.sa.rest.DocumentSchema; +import org.onap.aai.sa.rest.SettingConfiguration; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException.ErrorMessage; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; +import org.onap.aai.sa.searchdbabstraction.entity.Document; +import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.ErrorResult; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResultBuilder; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResultBuilder.Type; +import org.onap.aai.sa.searchdbabstraction.entity.SearchHit; +import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; +import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.SuggestHit; +import org.onap.aai.sa.searchdbabstraction.entity.SuggestHits; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.onap.aai.sa.searchdbabstraction.util.AggregationParsingUtil; +import org.onap.aai.sa.searchdbabstraction.util.DocumentSchemaUtil; +import org.onap.aai.sa.searchdbabstraction.util.ElasticSearchPayloadTranslator; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; + +/** + * This class has the Elasticsearch implementation of the DB operations defined in DocumentStoreInterface. + */ +public class ElasticSearchHttpController implements DocumentStoreInterface { + + private static ElasticSearchHttpController instance = null; + + private static final Logger logger = + LoggerFactory.getInstance().getLogger(ElasticSearchHttpController.class.getName()); + private static final Logger metricsLogger = + LoggerFactory.getInstance().getMetricsLogger(ElasticSearchHttpController.class.getName()); + + private static final String URL_QUERY_VERSION = "version="; + + private static final String JSON_ATTR_VERSION = "_version"; + private static final String JSON_ATTR_ERROR = "error"; + private static final String JSON_ATTR_REASON = "reason"; + + private static final String DEFAULT_TYPE = "default"; + + private static final String MSG_RESOURCE_MISSING = "Specified resource does not exist: "; + private static final String MSG_RESPONSE_CODE = "Response Code : "; + private static final String MSG_INVALID_DOCUMENT_URL = "Invalid document URL: "; + + private static final String FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE = "Failed to parse Elastic Search response."; + + private static final String BULK_CREATE_WITHOUT_INDEX_TEMPLATE = + "{\"create\":{\"_index\" : \"%s\", \"_type\" : \"%s\"} }\n"; + private static final String BULK_CREATE_WITH_INDEX_TEMPLATE = + "{\"create\":{\"_index\" : \"%s\", \"_type\" : \"%s\", \"_id\" : \"%s\" } }\n"; + private static final String BULK_IMPORT_INDEX_TEMPLATE = + "{\"index\":{\"_index\":\"%s\",\"_type\":\"%s\",\"_id\":\"%s\", \"_version\":\"%s\"}}\n"; + private static final String BULK_DELETE_TEMPLATE = + "{ \"delete\": { \"_index\": \"%s\", \"_type\": \"%s\", \"_id\": \"%s\", \"_version\":\"%s\"}}\n"; + public final static String APPLICATION_XND_JSON_TYPE = new MediaType("application", "x-ndjson").toString(); + + private final ElasticSearchConfig config; + + protected AnalysisConfiguration analysisConfig; + protected SettingConfiguration settingConfig; + + public ElasticSearchHttpController(ElasticSearchConfig config) { + this.config = config; + analysisConfig = new AnalysisConfiguration(); + settingConfig = new SettingConfiguration(); + + String rootUrl = null; + try { + if ("https".equals(config.getUriScheme())) { + new ElasticSearchHttpsController(config); + } + rootUrl = buildUrl(createUriBuilder("")).toString(); + logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_ATTEMPT, rootUrl); + checkConnection(); + logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_SUCCESS, rootUrl); + } catch (Exception e) { + logger.error(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_FAILURE, null, e, rootUrl, e.getMessage()); + } + } + + public static ElasticSearchHttpController getInstance() { + synchronized (ElasticSearchHttpController.class) { + if (instance == null) { + Properties properties = new Properties(); + File file = new File(SearchDbConstants.ES_CONFIG_FILE); + try { + properties.load(new FileInputStream(file)); + } catch (Exception e) { + logger.error(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "ElasticSearchHTTPController.getInstance", + e.getLocalizedMessage()); + } + + ElasticSearchConfig config = new ElasticSearchConfig(properties); + instance = new ElasticSearchHttpController(config); + } + } + + return instance; + } + + public AnalysisConfiguration getAnalysisConfig() { + return analysisConfig; + } + + public ElasticSearchConfig getElasticSearchConfig() { + return config; + } + + @Override + public OperationResult createIndex(String index, DocumentSchema documentSchema) { + try { + // Submit the request to ElasticSearch to create the index using a default document type. + OperationResult result = createTable(index, DEFAULT_TYPE, analysisConfig, + DocumentSchemaUtil.generateDocumentMappings(documentSchema), settingConfig); + + // ElasticSearch will return us a 200 code on success when we + // want to report a 201, so translate the result here. + if (result.getResultCode() == Status.OK.getStatusCode()) { + result.setResultCode(Status.CREATED.getStatusCode()); + } + + if (isSuccess(result)) { + result.setResult("{\"url\": \"" + ApiUtils.buildIndexUri(index) + "\"}"); + } + return result; + } catch (DocumentStoreOperationException | IOException e) { + return new OperationResultBuilder().useDefaults() + .failureCause("Document store operation failure. Cause: " + e.getMessage()).build(); + } + } + + @Override + public OperationResult createDynamicIndex(String index, String dynamicSchema) { + try { + OperationResult result = createTable(index, dynamicSchema); + + // ElasticSearch will return us a 200 code on success when we + // want to report a 201, so translate the result here. + if (result.getResultCode() == Status.OK.getStatusCode()) { + result.setResultCode(Status.CREATED.getStatusCode()); + } + if (isSuccess(result)) { + result.setResult("{\"url\": \"" + ApiUtils.buildIndexUri(index) + "\"}"); + } + return result; + } catch (DocumentStoreOperationException e) { + return new OperationResultBuilder().useDefaults() + .failureCause("Document store operation failure. Cause: " + e.getMessage()).build(); + } + } + + @Override + public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.DELETE); + OperationResult opResult = handleResponse(conn); + logMetricsInfo(override, SearchDbMsgs.DELETE_INDEX_TIME, opResult, indexName); + shutdownConnection(conn); + + return opResult; + } + + // @Override + protected OperationResult createTable(String indexName, String typeName, AnalysisConfiguration ac, + String indexMappings, SettingConfiguration sc) throws DocumentStoreOperationException { + if (ac.getEsIndexSettings() == null) { + logger.debug("No analysis settings provided."); + } + + if (indexMappings == null) { + logger.debug("No mappings provided."); + } + + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); + + StringBuilder sb = new StringBuilder(128); + sb.append("{ \"settings\" : "); + sb.append(sc.getSettingsWithAnalysis(ac)); + sb.append(","); + + sb.append("\"mappings\" : {"); + sb.append("\"" + typeName + "\" :"); + sb.append(indexMappings); + sb.append("}}"); + + try { + attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(sb.toString())); + } catch (IOException e) { + logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); + throw new DocumentStoreOperationException(e.getMessage(), e); + } + + logger.debug("Request content: " + sb); + + OperationResult opResult = handleResponse(conn); + shutdownConnection(conn); + logMetricsInfo(override, SearchDbMsgs.CREATE_INDEX_TIME, opResult, indexName); + + return opResult; + } + + /** + * Will send the passed in JSON payload to Elasticsearch using the provided index name in an attempt to create the + * index. + * + * @param indexName - The name of the index to be created + * @param settingsAndMappings - The actual JSON object that will define the index + * @return - The operation result of writing into Elasticsearch + * @throws DocumentStoreOperationException + */ + protected OperationResult createTable(String indexName, String settingsAndMappings) + throws DocumentStoreOperationException { + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); + try { + attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(settingsAndMappings)); + } catch (IOException e) { + logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); + throw new DocumentStoreOperationException(e.getMessage()); + } + + OperationResult result = handleResponse(conn); + logMetricsInfo(override, SearchDbMsgs.CREATE_INDEX_TIME, result, indexName); + + return result; + } + + @Override + public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { + + if (!allowImplicitIndexCreation) { + // Before we do anything, make sure that the specified index actually exists in the + // document store - we don't want to rely on ElasticSearch to fail the document + // create because it could be configured to implicitly create a non-existent index, + // which can lead to hard-to-debug behaviour with queries down the road. + OperationResult indexExistsResult = checkIndexExistence(indexName); + if (!isSuccess(indexExistsResult)) { + String resultMsg = "Document Index '" + indexName + "' does not exist."; + return (DocumentOperationResult) new OperationResultBuilder(Type.DOCUMENT).status(Status.NOT_FOUND) + .result(resultMsg).failureCause(resultMsg).build(); + } + } + + if (document.getId() == null || document.getId().isEmpty()) { + return createDocumentWithoutId(indexName, document); + } else { + return createDocumentWithId(indexName, document); + } + } + + @Override + public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { + if (!allowImplicitIndexCreation) { + // Before we do anything, make sure that the specified index actually exists in the + // document store - we don't want to rely on ElasticSearch to fail the document + // create because it could be configured to implicitly create a non-existent index, + // which can lead to hard-to-debug behaviour with queries down the road. + OperationResult indexExistsResult = checkIndexExistence(indexName); + if (!isSuccess(indexExistsResult)) { + DocumentOperationResult opResult = new DocumentOperationResult(); + opResult.setResultCode(Status.NOT_FOUND.getStatusCode()); + String resultMsg = "Document Index '" + indexName + "' does not exist."; + opResult.setResult(resultMsg); + opResult.setFailureCause(resultMsg); + return opResult; + } + } + + MdcOverride override = getStartTime(new MdcOverride()); + + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) + .replaceQuery(URL_QUERY_VERSION + document.getVersion())); + + HttpURLConnection conn = createConnection(url, HttpMethod.PUT); + attachDocument(conn, document); + + DocumentOperationResult opResult = getOperationResult(conn); + buildDocumentResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.UPDATE_DOCUMENT_TIME, opResult, indexName, document.getId()); + + shutdownConnection(conn); + + return opResult; + } + + @Override + public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) + .replaceQuery(URL_QUERY_VERSION + document.getVersion())); + + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(url, HttpMethod.DELETE); + + DocumentOperationResult opResult = getOperationResult(conn); + buildDocumentResult(opResult, indexName); + // supress the etag and url in response for delete as they are not required + if (opResult.getDocument() != null) { + opResult.getDocument().setEtag(null); + opResult.getDocument().setUrl(null); + } + + logMetricsInfo(override, SearchDbMsgs.DELETE_DOCUMENT_TIME, opResult, indexName, document.getId()); + + shutdownConnection(conn); + + return opResult; + } + + @Override + public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + final UriBuilder uriBuilder = createUriBuilder(indexName, DEFAULT_TYPE, document.getId()); + if (document.getVersion() != null) { + uriBuilder.replaceQuery(URL_QUERY_VERSION + document.getVersion()); + } + + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = createConnection(buildUrl(uriBuilder), "GET"); + + DocumentOperationResult opResult = getOperationResult(conn); + buildDocumentResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.GET_DOCUMENT_TIME, opResult, indexName, document.getId()); + + shutdownConnection(conn); + + return opResult; + } + + @Override + public SearchOperationResult search(String indexName, String queryString) throws DocumentStoreOperationException { + final URL url = buildUrl(createUriBuilder(indexName, "_search").replaceQuery(queryString)); + + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(url, "GET"); + SearchOperationResult opResult = getSearchOperationResult(conn); + buildSearchResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, queryString); + + return opResult; + } + + @Override + public SearchOperationResult searchWithPayload(String indexName, String query) + throws DocumentStoreOperationException { + if (logger.isDebugEnabled()) { + logger.debug("Querying index: " + indexName + " with query string: " + query); + } + final URL url = buildUrl(createUriBuilder(indexName, "_search")); + + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(url, HttpMethod.POST); + attachContent(conn, query); + logger.debug("Request body = Elasticsearch query = " + query); + + SearchOperationResult opResult = getSearchOperationResult(conn); + buildSearchResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, query); + + shutdownConnection(conn); + + return opResult; + } + + @Override + public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) + throws DocumentStoreOperationException { + if (logger.isDebugEnabled()) { + logger.debug("Querying Suggestion index: " + indexName + " with query string: " + query); + } + + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName, "_suggest")), HttpMethod.POST); + attachContent(conn, query); + + logger.debug("Request body = Elasticsearch query = " + query); + + SearchOperationResult opResult = getSearchOperationResult(conn); + buildSuggestResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, query); + + shutdownConnection(conn); + + return opResult; + } + + @Override + public OperationResult performBulkOperations(BulkRequest[] requests) throws DocumentStoreOperationException { + if (logger.isDebugEnabled()) { + StringBuilder dbgString = new StringBuilder("ESController: performBulkOperations - Operations: "); + + for (BulkRequest request : requests) { + dbgString.append("[").append(request).append("] "); + } + + logger.debug(dbgString.toString()); + } + + MdcOverride override = getStartTime(new MdcOverride()); + + // Parse the supplied set of operations. + // Iterate over the list of operations which we were provided and + // translate them into a format that ElasticSearh understands. + int opCount = 0; + StringBuilder esOperationSet = new StringBuilder(128); + List rejected = new ArrayList<>(); + for (BulkRequest request : requests) { + + // Convert the request to the syntax ElasticSearch likes. + if (buildEsOperation(request, esOperationSet, rejected)) { + opCount++; + } + } + + ElasticSearchBulkOperationResult opResult = null; + if (opCount > 0) { + HttpURLConnection conn; + try { + conn = (HttpURLConnection) buildUrl(createUriBuilder("_bulk")).openConnection(); + conn.setRequestMethod(HttpMethod.PUT); + conn.setDoOutput(true); + conn.setRequestProperty(CONTENT_TYPE, APPLICATION_XND_JSON_TYPE); + if(config.useAuth()){ + conn.setRequestProperty("Authorization", config.getAuthValue()); + } + conn.setRequestProperty("Connection", "Close"); + + } catch (IOException e) { + + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(Throwables.getStackTraceAsString(e)); + } + + throw new DocumentStoreOperationException( + "Failed to open connection to document store. Cause: " + e.getMessage(), e); + } + + StringBuilder bulkResult = new StringBuilder(128); + try { + // Create an output stream to write our request to. + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + + if (logger.isDebugEnabled()) { + logger.debug("ESController: Sending 'BULK' request to " + conn.getURL()); + logger.debug("ESController: operations: " + esOperationSet.toString().replaceAll("\n", "\\n")); + } + + // Write the resulting request string to our output stream. (this sends the request to ES?) + out.write(esOperationSet.toString()); + out.close(); + + // Open an input stream on our connection in order to read back the results. + InputStream is = conn.getInputStream(); + InputStreamReader inputstreamreader = new InputStreamReader(is); + BufferedReader bufferedreader = new BufferedReader(inputstreamreader); + + // Read the contents of the input stream into our result string... + String esResponseString = null; + + while ((esResponseString = bufferedreader.readLine()) != null) { + bulkResult.append(esResponseString).append("\n"); + } + + } catch (IOException e) { + + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); + if (logger.isDebugEnabled()) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + logger.debug(sw.toString()); + } + + throw new DocumentStoreOperationException( + "Failure interacting with document store. Cause: " + e.getMessage(), e); + } + + if (logger.isDebugEnabled()) { + logger.debug("ESController: Received result string from ElasticSearch: = " + bulkResult.toString()); + } + + // ...and marshal the resulting string into a Java object. + try { + opResult = marshallEsBulkResult(bulkResult.toString()); + + } catch (IOException e) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(Throwables.getStackTraceAsString(e)); + } + + throw new DocumentStoreOperationException("Failed to marshal response body. Cause: " + e.getMessage(), + e); + } + } + + OperationResult result = new OperationResultBuilder() // + .resultCode(HttpStatus.MULTI_STATUS_207) // + .result(buildGenericBulkResultSet(opResult, rejected)) // + .build(); + + // In the success case we don't want the entire result string to be dumped into the metrics log, so concatenate + // it. + String resultStringForMetricsLog = result.getResult(); + if (isSuccess(result)) { + resultStringForMetricsLog = + resultStringForMetricsLog.substring(0, Math.max(resultStringForMetricsLog.length(), 85)) + "..."; + } + + metricsLogger.info(SearchDbMsgs.BULK_OPERATIONS_TIME, + new LogFields() // + .setField(LogLine.DefinedFields.RESPONSE_CODE, result.getResultCode()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, resultStringForMetricsLog), + override); + + return result; + } + + + /** + * This method queryies ElasticSearch to determine if the supplied index is present in the document store. + * + * @param indexName - The index to look for. + * @return - An operation result indicating the success or failure of the check. + * @throws DocumentStoreOperationException + */ + private OperationResult checkIndexExistence(String indexName) throws DocumentStoreOperationException { + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.HEAD); + int resultCode; + try { + resultCode = conn.getResponseCode(); + } catch (IOException ex) { + shutdownConnection(conn); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); + } + logger.debug(MSG_RESPONSE_CODE + resultCode); + + OperationResult opResult = new OperationResultBuilder().useDefaults().resultCode(resultCode).build(); + logMetricsInfo(override, SearchDbMsgs.CHECK_INDEX_TIME, opResult, indexName); + shutdownConnection(conn); + + return opResult; + } + + private DocumentOperationResult createDocumentWithId(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + // check if the document already exists + DocumentOperationResult opResult = checkDocumentExistence(indexName, document.getId()); + + if (opResult.getResultCode() != Status.NOT_FOUND.getStatusCode()) { + if (opResult.getResultCode() == Status.CONFLICT.getStatusCode()) { + opResult.setFailureCause("A document with the same id already exists."); + } else { + opResult.setFailureCause("Failed to verify a document with the specified id does not already exist."); + } + opResult.setResultCode(Status.CONFLICT.getStatusCode()); + return opResult; + } + + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId())); + MdcOverride override = getStartTime(new MdcOverride()); + + HttpURLConnection conn = createConnection(url, HttpMethod.PUT); + attachDocument(conn, document); + + opResult = getOperationResult(conn); + buildDocumentResult(opResult, indexName); + + logMetricsInfo(override, SearchDbMsgs.CREATE_DOCUMENT_TIME, opResult, indexName); + + shutdownConnection(conn); + + return opResult; + } + + private DocumentOperationResult createDocumentWithoutId(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE)); + + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = createConnection(url, HttpMethod.POST); + attachDocument(conn, document); + + DocumentOperationResult response = getOperationResult(conn); + buildDocumentResult(response, indexName); + + logMetricsInfo(override, SearchDbMsgs.CREATE_DOCUMENT_TIME, response, indexName); + + shutdownConnection(conn); + + return response; + } + + private void attachDocument(HttpURLConnection conn, DocumentStoreDataEntity doc) + throws DocumentStoreOperationException { + conn.setRequestProperty("Connection", "Close"); + attachContent(conn, doc.getContentInJson()); + } + + private DocumentOperationResult checkDocumentExistence(String indexName, String docId) + throws DocumentStoreOperationException { + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = + createConnection(buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, docId)), HttpMethod.HEAD); + int resultCode; + try { + resultCode = conn.getResponseCode(); + } catch (IOException ex) { + shutdownConnection(conn); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); + } + + logger.debug(MSG_RESPONSE_CODE + resultCode); + + DocumentOperationResult opResult = (DocumentOperationResult) new OperationResultBuilder(Type.DOCUMENT) + .useDefaults().resultCode(resultCode).build(); + + logMetricsInfo(override, SearchDbMsgs.GET_DOCUMENT_TIME, opResult, indexName, docId); + shutdownConnection(conn); + + return opResult; + } + + private void attachContent(HttpURLConnection conn, String content) throws DocumentStoreOperationException { + OutputStream outputStream = null; + OutputStreamWriter out = null; + + try { + outputStream = conn.getOutputStream(); + } catch (IOException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to get connection output stream.", e); + } + + out = new OutputStreamWriter(outputStream); + + try { + out.write(content); + out.close(); + } catch (IOException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to write to the output stream.", e); + } + } + + private HttpURLConnection initializeConnection(URL url) throws DocumentStoreOperationException { + HttpURLConnection conn = null; + try { + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON); + conn.setDoOutput(true); + if (config.useAuth()) { + conn.setRequestProperty("Authorization", config.getAuthValue()); + } + } catch (IOException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to open connection to URL " + url, e); + } + + return conn; + } + + private OperationResult handleResponse(HttpURLConnection conn) throws DocumentStoreOperationException { + return handleResponse(conn, new OperationResultBuilder().useDefaults()); + } + + private OperationResult handleResponse(HttpURLConnection conn, OperationResultBuilder rb) + throws DocumentStoreOperationException { + int resultCode; + + try { + resultCode = conn.getResponseCode(); + } catch (IOException ex) { + shutdownConnection(conn); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); + } + + logger.debug(MSG_RESPONSE_CODE + resultCode); + + InputStream inputStream = null; + + if (!ApiUtils.isSuccessStatusCode(resultCode)) { + inputStream = conn.getErrorStream(); + } else { + try { + inputStream = conn.getInputStream(); + } catch (IOException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to get the response input stream.", e); + } + } + + InputStreamReader inputstreamreader = new InputStreamReader(inputStream); + BufferedReader bufferedreader = new BufferedReader(inputstreamreader); + + StringBuilder result = new StringBuilder(128); + String string = null; + + try { + while ((string = bufferedreader.readLine()) != null) { + result.append(string).append("\n"); + } + } catch (IOException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed getting the response body payload.", e); + } + + if (resultCode == Status.CONFLICT.getStatusCode()) { + rb.resultCode(Status.PRECONDITION_FAILED.getStatusCode()); + } else { + rb.resultCode(resultCode); + } + if (logger.isDebugEnabled()) { + logger.debug("Raw result string from ElasticSearch = " + result.toString()); + } + rb.result(result.toString()); + rb.resultVersion(extractVersion(result.toString())); + return rb.build(); + } + + private String extractVersion(String result) { + JSONParser parser = new JSONParser(); + String version = null; + try { + JSONObject root = (JSONObject) parser.parse(result); + if (root.get(JSON_ATTR_VERSION) != null) { + version = root.get(JSON_ATTR_VERSION).toString(); + } + } catch (ParseException e) { + // Not all responses from ElasticSearch include a version, so + // if we don't get one back, just return an empty string rather + // than trigger a false failure. + version = ""; + } + return version; + } + + /** + * This convenience method gets the current system time and stores it in an attribute in the supplied + * {@link MdcOverride} object so that it can be used later by the metrics logger. + * + * @param override - The {@link MdcOverride} object to update. + * @return - The supplied {@link MdcOverride} object. + */ + private MdcOverride getStartTime(MdcOverride override) { + + // Grab the current time... + long startTimeInMs = System.currentTimeMillis(); + + // ...and add it as an attribute to the supplied MDC Override object. + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + override.addAttribute(MdcContext.MDC_START_TIME, formatter.format(startTimeInMs)); + + // Return the MdcOverride object that we were passed. + // This looks odd, but it allows us to do stuff like: + // + // MdcOverride ov = getStartTime(new MdcOverride()) + // + // which is quite handy, but also allows us to pass in an existing + // MdcOverride object which already has some attributes set. + return override; + } + + private boolean isSuccess(OperationResult result) { + return ApiUtils.isSuccessStatusCode(result.getResultCode()); + } + + private UriBuilder createUriBuilder(String path, String... paths) { + UriBuilder builder = UriBuilder.fromPath(path); + for (String other : paths) { + builder.path(other); + } + builder.host(config.getIpAddress()); + String port = Optional.ofNullable(config.getHttpPort()).orElse("0"); + builder.port(Integer.valueOf(port)); + builder.scheme(config.getUriScheme()); + return builder; + } + + private URL buildUrl(UriBuilder builder) throws DocumentStoreOperationException { + try { + return builder.build().toURL(); + } catch (MalformedURLException e) { + logger.error(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "buildUrl", e.getLocalizedMessage()); + throw new DocumentStoreOperationException("Error building a URL with " + builder.toString(), e); + } + } + + private HttpURLConnection createConnection(final URL url, final String method) + throws DocumentStoreOperationException { + HttpURLConnection conn = initializeConnection(url); + try { + logger.debug("\nSending '" + method + "' request to URL : " + conn.getURL()); + conn.setRequestMethod(method); + } catch (ProtocolException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException(ErrorMessage.SET_REQUEST_METHOD_FAILED, e, method); + } + return conn; + } + + private OperationResult checkConnection() throws IOException, DocumentStoreOperationException { + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder("_cluster/health")), HttpMethod.GET); + int resultCode = conn.getResponseCode(); + logger.debug("getClusterHealth() response Code : " + resultCode); + shutdownConnection(conn); + return new OperationResultBuilder().resultCode(resultCode).build(); + } + + private void shutdownConnection(HttpURLConnection connection) { + if (connection == null) { + return; + } + + final String methodName = "shutdownConnection"; + InputStream inputstream = null; + OutputStream outputstream = null; + + try { + inputstream = connection.getInputStream(); + } catch (IOException e) { + logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); + } finally { + if (inputstream != null) { + try { + inputstream.close(); + } catch (IOException e) { + logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); + } + } + } + + try { + outputstream = connection.getOutputStream(); + } catch (IOException e) { + logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); + } finally { + if (outputstream != null) { + try { + outputstream.close(); + } catch (IOException e) { + logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); + } + } + } + + connection.disconnect(); + } + + /** + * This method converts a {@link BulkRequest} object into a json structure which can be understood by ElasticSearch. + * + * @param request - The request to be performed. + * @param sb - The string builder to append the json data to + * @throws DocumentStoreOperationException + */ + private boolean buildEsOperation(BulkRequest request, StringBuilder sb, List fails) + throws DocumentStoreOperationException { + + boolean retVal = true; + // What kind of operation are we performing? + switch (request.getOperationType()) { + + // Create a new document. + case CREATE: + + // Make sure that we were supplied a document payload. + if (request.getOperation().getDocument() == null) { + + fails.add(generateRejectionEntry(request.getOperationType(), "Missing document payload", + request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Make sure that the supplied document URL is formatted + // correctly. + if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), false)) { + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), + request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Validate that the specified index actually exists before we + // try to perform the create. + if (!indexExists(ApiUtils.extractIndexFromUri(request.getOperation().getMetaData().getUrl()))) { + + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), + request.getId(), 404, request.getOperation().getMetaData().getUrl())); + return false; + } + + // If we were supplied an id for the new document, then + // include it in the bulk operation to Elastic Search + if (request.getId() == null) { + + sb.append(String.format(BULK_CREATE_WITHOUT_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE)); + + // Otherwise, we just leave that parameter off and ElasticSearch + // will generate one for us. + } else { + sb.append(String.format(BULK_CREATE_WITH_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE, + request.getId())); + } + + try { + // Append the document that we want to create. + sb.append(request.getOperation().getDocument().toJson()).append("\n"); + } catch (JsonProcessingException e) { + throw new DocumentStoreOperationException("Failure parsing document to json", e); + } + + break; + + // Update an existing document. + case UPDATE: + + // Make sure that we were supplied a document payload. + if (request.getOperation().getDocument() == null) { + + fails.add(generateRejectionEntry(request.getOperationType(), "Missing document payload", + request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Make sure that the supplied document URL is formatted + // correctly. + if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), true)) { + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), + request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Validate that the specified index actually exists before we + // try to perform the update. + if (!indexExists(request.getIndex())) { + + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), + request.getId(), 404, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Validate that the document we are trying to update actually + // exists before we try to perform the update. + if (!documentExists(request.getIndex(), request.getId())) { + + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), + request.getId(), 404, request.getOperation().getMetaData().getUrl())); + return false; + } + + // It is mandatory that a version be supplied for an update operation, + // so validate that now. + if (request.getOperation().getMetaData().getEtag() == null) { + + fails.add(generateRejectionEntry(request.getOperationType(), "Missing mandatory ETag field", + request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Generate the update request... + sb.append(String.format(BULK_IMPORT_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE, request.getId(), + request.getOperation().getMetaData().getEtag())); + + // ...and append the document that we want to update. + try { + sb.append(request.getOperation().getDocument().toJson()).append("\n"); + } catch (JsonProcessingException e) { + throw new DocumentStoreOperationException("Failure parsing document to json", e); + } + break; + + // Delete an existing document. + case DELETE: + + // Make sure that the supplied document URL is formatted + // correctly. + if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), true)) { + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), + request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Validate that the specified index actually exists before we + // try to perform the delete. + if (!indexExists(request.getIndex())) { + + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), + request.getId(), 404, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Validate that the document we are trying to update actually + // exists before we try to perform the delete. + if (!documentExists(request.getIndex(), request.getId())) { + + fails.add(generateRejectionEntry(request.getOperationType(), + MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), + request.getId(), 404, request.getOperation().getMetaData().getUrl())); + return false; + } + + // It is mandatory that a version be supplied for a delete operation, + // so validate that now. + if (request.getOperation().getMetaData().getEtag() == null) { + + fails.add(generateRejectionEntry(request.getOperationType(), "Missing mandatory ETag field", + request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); + return false; + } + + // Generate the delete request. + sb.append(String.format(BULK_DELETE_TEMPLATE, request.getIndex(), DEFAULT_TYPE, request.getId(), + request.getOperation().getMetaData().getEtag())); + break; + default: + } + + return retVal; + } + + private boolean indexExists(String index) throws DocumentStoreOperationException { + return isSuccess(checkIndexExistence(index)); + } + + private boolean documentExists(String index, String id) throws DocumentStoreOperationException { + return isSuccess(checkDocumentExistence(index, id)); + } + + /** + * This method constructs a status entry for a bulk operation which has been rejected before even sending it to the + * document store. + * + * @param rejectReason - A message describing why the operation was rejected. + * @param anId - The identifier associated with the document being acted on. + * @param statusCode - An HTTP status code. + * @return - A result set item. + */ + private ElasticSearchResultItem generateRejectionEntry(OperationType opType, String rejectReason, String index, + String anId, int statusCode, String originalUrl) { + + ElasticSearchError err = new ElasticSearchError(); + err.setReason(rejectReason); + + ElasticSearchOperationStatus op = new ElasticSearchOperationStatus(); + op.setIndex(index); + op.setId(anId); + op.setStatus(statusCode); + op.setError(err); + op.setAdditionalProperties(ElasticSearchResultItem.REQUEST_URL, originalUrl); + + ElasticSearchResultItem rejectionResult = new ElasticSearchResultItem(); + + switch (opType) { + case CREATE: + rejectionResult.setCreate(op); + break; + case UPDATE: + rejectionResult.setIndex(op); + break; + case DELETE: + rejectionResult.setDelete(op); + break; + default: + } + + return rejectionResult; + } + + /** + * This method takes the json structure returned from ElasticSearch in response to a bulk operations request and + * marshals it into a Java object. + * + * @param jsonResult - The bulk operations response returned from ElasticSearch. + * @return - The marshalled response. + * @throws JsonParseException + * @throws JsonMappingException + * @throws IOException + */ + private ElasticSearchBulkOperationResult marshallEsBulkResult(String jsonResult) throws IOException { + if (jsonResult != null) { + if (logger.isDebugEnabled()) { + logger.debug("ESController: Marshalling ES result set from json: " + jsonResult.replaceAll("\n", "")); + } + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_EMPTY); + + return mapper.readValue(jsonResult, ElasticSearchBulkOperationResult.class); + } + + return null; + } + + /** + * This method takes the marshalled ElasticSearch bulk response and converts it into a generic response payload. + * + * @param esResult - ElasticSearch bulk operations response. + * @return - A generic result set. + */ + private String buildGenericBulkResultSet(ElasticSearchBulkOperationResult esResult, + List rejectedOps) { + int totalOps = 0; + int totalSuccess = 0; + int totalFails = 0; + + if (logger.isDebugEnabled()) { + + logger.debug("ESController: Build generic result set. ES Results: " + + ((esResult != null) ? esResult.toString() : "[]") + " Rejected Ops: " + rejectedOps.toString()); + } + + // Build a combined list of result items from the results returned + // from ElasticSearch and the list of operations that we rejected + // without sending to ElasticSearch. + List combinedResults = new ArrayList<>(); + if (esResult != null) { + combinedResults.addAll(Arrays.asList(esResult.getItems())); + } + combinedResults.addAll(rejectedOps); + + // Iterate over the individual results in the resulting result set. + StringBuilder resultsBuilder = new StringBuilder(); + AtomicBoolean firstItem = new AtomicBoolean(true); + for (ElasticSearchResultItem item : combinedResults) { + + // Increment the operation counts. + totalOps++; + if (ApiUtils.isSuccessStatusCode(item.operationStatus().getStatus())) { + totalSuccess++; + } else { + totalFails++; + } + + // Prepend a comma to our response string unless this it the + // first result in the set. + if (!firstItem.compareAndSet(true, false)) { + resultsBuilder.append(", "); + } + + // Append the current result as a generic json structure. + resultsBuilder.append(item.toJson()); + } + + return "{ \"total_operations\": " + totalOps + ", " + "\"total_success\": " + totalSuccess + ", " + + "\"total_fails\": " + totalFails + ", " + "\"results\": [" + resultsBuilder.toString() + "]}"; + } + + private DocumentOperationResult getOperationResult(HttpURLConnection conn) throws DocumentStoreOperationException { + return (DocumentOperationResult) handleResponse(conn, new OperationResultBuilder(Type.DOCUMENT).useDefaults()); + } + + private SearchOperationResult getSearchOperationResult(HttpURLConnection conn) + throws DocumentStoreOperationException { + return (SearchOperationResult) handleResponse(conn, new OperationResultBuilder(Type.SEARCH).useDefaults()); + } + + private void buildDocumentResult(DocumentOperationResult result, String index) + throws DocumentStoreOperationException { + + JSONParser parser = new JSONParser(); + JSONObject root; + try { + root = (JSONObject) parser.parse(result.getResult()); + if (isSuccess(result)) { + // Success response object + Document doc = new Document(); + doc.setEtag(result.getResultVersion()); + doc.setUrl(buildDocumentResponseUrl(index, root.get("_id").toString())); + + doc.setContent((JSONObject) root.get("_source")); + result.setDocument(doc); + + } else { + // Error response object + JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); + if (error != null) { + result.setError( + new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); + } + + } + } catch (Exception e) { + throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); + } + } + + private String buildDocumentResponseUrl(String index, String id) { + return ApiUtils.buildDocumentUri(index, id); + } + + private void buildSearchResult(SearchOperationResult result, String index) throws DocumentStoreOperationException { + JSONParser parser = new JSONParser(); + JSONObject root; + + try { + root = (JSONObject) parser.parse(result.getResult()); + if (isSuccess(result)) { + JSONObject hits = (JSONObject) root.get("hits"); + JSONArray hitArray = (JSONArray) hits.get("hits"); + SearchHits searchHits = new SearchHits(); + searchHits.setTotalHits(hits.get("total").toString()); + ArrayList searchHitArray = new ArrayList<>(); + + for (int i = 0; i < hitArray.size(); i++) { + JSONObject hit = (JSONObject) hitArray.get(i); + SearchHit searchHit = new SearchHit(); + searchHit.setScore((hit.get("_score") != null) ? hit.get("_score").toString() : ""); + Document doc = new Document(); + if (hit.get(JSON_ATTR_VERSION) != null) { + doc.setEtag((hit.get(JSON_ATTR_VERSION) != null) ? hit.get(JSON_ATTR_VERSION).toString() : ""); + } + + doc.setUrl( + buildDocumentResponseUrl(index, (hit.get("_id") != null) ? hit.get("_id").toString() : "")); + doc.setContent((JSONObject) hit.get("_source")); + searchHit.setDocument(doc); + searchHitArray.add(searchHit); + } + searchHits.setHits(searchHitArray.toArray(new SearchHit[searchHitArray.size()])); + result.setSearchResult(searchHits); + + JSONObject aggregations = (JSONObject) root.get("aggregations"); + if (aggregations != null) { + AggregationResult[] aggResults = AggregationParsingUtil.parseAggregationResults(aggregations); + AggregationResults aggs = new AggregationResults(); + aggs.setAggregations(aggResults); + result.setAggregationResult(aggs); + } + + // success + } else { + JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); + if (error != null) { + result.setError( + new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); + } + } + } catch (Exception e) { + throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); + } + } + + private void buildSuggestResult(SearchOperationResult result, String index) throws DocumentStoreOperationException { + JSONParser parser = new JSONParser(); + JSONObject root; + try { + root = (JSONObject) parser.parse(result.getResult()); + if (isSuccess(result)) { + JSONArray hitArray = (JSONArray) root.get("suggest-vnf"); + JSONObject hitdata = (JSONObject) hitArray.get(0); + JSONArray optionsArray = (JSONArray) hitdata.get("options"); + SuggestHits suggestHits = new SuggestHits(); + suggestHits.setTotalHits(String.valueOf(optionsArray.size())); + + ArrayList suggestHitArray = new ArrayList<>(); + + for (int i = 0; i < optionsArray.size(); i++) { + JSONObject hit = (JSONObject) optionsArray.get(i); + + SuggestHit suggestHit = new SuggestHit(); + suggestHit.setScore((hit.get("score") != null) ? hit.get("score").toString() : ""); + suggestHit.setText((hit.get("text") != null) ? hit.get("text").toString() : ""); + Document doc = new Document(); + if (hit.get(JSON_ATTR_VERSION) != null) { + doc.setEtag((hit.get(JSON_ATTR_VERSION) != null) ? hit.get(JSON_ATTR_VERSION).toString() : ""); + } + doc.setUrl( + buildDocumentResponseUrl(index, (hit.get("_id") != null) ? hit.get("_id").toString() : "")); + + doc.setContent((JSONObject) hit.get("payload")); + suggestHit.setDocument(doc); + suggestHitArray.add(suggestHit); + } + suggestHits.setHits(suggestHitArray.toArray(new SuggestHit[suggestHitArray.size()])); + result.setSuggestResult(suggestHits); + + JSONObject aggregations = (JSONObject) root.get("aggregations"); + if (aggregations != null) { + AggregationResult[] aggResults = AggregationParsingUtil.parseAggregationResults(aggregations); + AggregationResults aggs = new AggregationResults(); + aggs.setAggregations(aggResults); + result.setAggregationResult(aggs); + } + + // success + } else { + JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); + if (error != null) { + result.setError( + new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); + } + } + } catch (Exception e) { + throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); + } + } + + /** + * Record the timing of the operation in the metrics log. + * + */ + private void logMetricsInfo(MdcOverride override, SearchDbMsgs message, OperationResult operationResult, + String... args) { + metricsLogger.info(message, + new LogFields() // + .setField(LogLine.DefinedFields.RESPONSE_CODE, operationResult.getResultCode()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, operationResult.getResult()) + .setField(LogLine.DefinedFields.SERVER_IP, "ElasticHost-"+config.getIpAddress()), + override, args); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java new file mode 100644 index 0000000..51b8952 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java @@ -0,0 +1,148 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; + +/** + * HTTPS (TLS) specific configuration. + */ +public class ElasticSearchHttpsController { + + private static final Logger logger = + LoggerFactory.getInstance().getLogger(ElasticSearchHttpsController.class.getName()); + + private static final String SSL_PROTOCOL = "TLS"; + private static final String KEYSTORE_ALGORITHM = "SunX509"; + private static final String KEYSTORE_TYPE = "PKCS12"; + + public ElasticSearchHttpsController(ElasticSearchConfig config) throws NoSuchAlgorithmException, KeyStoreException, + CertificateException, IOException, KeyManagementException, UnrecoverableKeyException { + logger.debug("Initialising HTTPS configuration"); + + SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); + KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); + + String clientCertPassword = config.getKeyStorePassword(); + + char[] pwd = null; + if (clientCertPassword != null) { + pwd = clientCertPassword.toCharArray(); + } else { + logger.debug("No key store password is defined"); + } + + TrustManager[] trustManagers = getTrustManagers(config); + KeyManager[] keyManagers = null; + + String clientCertFileName = config.getKeyStorePath(); + if (clientCertFileName != null) { + InputStream fin = Files.newInputStream(Paths.get(clientCertFileName)); + keyStore.load(fin, pwd); + kmf.init(keyStore, pwd); + keyManagers = kmf.getKeyManagers(); + } + + ctx.init(keyManagers, trustManagers, null); + logger.debug("Initialised SSL context"); + + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> host.equalsIgnoreCase(session.getPeerHost())); + } + + private TrustManager[] getTrustManagers(ElasticSearchConfig config) + throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + // Using null here initializes the TMF with the default trust store. + tmf.init((KeyStore) null); + + // Find the default trust manager. + final X509TrustManager defaultTrustManager = findX509TrustManager(tmf); + + String trustStoreFile = config.getTrustStorePath(); + if (trustStoreFile == null) { + logger.debug("No trust store defined"); + return new TrustManager[] {defaultTrustManager}; + } + + // Create a new Trust Manager from the local trust store. + try (InputStream myKeys = Files.newInputStream(Paths.get(trustStoreFile))) { + KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + char[] pwdArray = null; + if (config.getTrustStorePassword() != null) { + pwdArray = config.getTrustStorePassword().toCharArray(); + } + myTrustStore.load(myKeys, pwdArray); + tmf.init(myTrustStore); + } + + // Create a custom trust manager that wraps both our trust store and the default. + final X509TrustManager finalLocalTm = findX509TrustManager(tmf); + + return new TrustManager[] {new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return defaultTrustManager.getAcceptedIssuers(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + finalLocalTm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + defaultTrustManager.checkServerTrusted(chain, authType); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + defaultTrustManager.checkClientTrusted(chain, authType); + } + }}; + } + + private X509TrustManager findX509TrustManager(TrustManagerFactory tmf) { + return (X509TrustManager) Arrays.asList(tmf.getTrustManagers()).stream() + .filter(tm -> tm instanceof X509TrustManager).findFirst().orElse(null); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java new file mode 100644 index 0000000..6374716 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java @@ -0,0 +1,112 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import java.util.HashMap; +import java.util.Map; + +public class ElasticSearchOperationStatus { + + private String index; + private String type; + private String id; + private String version; + private ElasticSearchShardStatus shards; + private Integer status; + private ElasticSearchError error; + + private Map additionalProperties = new HashMap<>(); + + public ElasticSearchError getError() { + return error; + } + + public void setError(ElasticSearchError error) { + this.error = error; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public ElasticSearchShardStatus getShards() { + return shards; + } + + public void setShards(ElasticSearchShardStatus shards) { + this.shards = shards; + } + + public String getIndex() { + return index; + } + + public void setIndex(String index) { + this.index = index; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperties(String name, Object value) { + additionalProperties.put(name, value); + } + + @Override + public String toString() { + return "ElasticSearchIndexStatus [index=" + index + ", type=" + type + ", id=" + id + ", version=" + version + + ", shards=" + shards + ", status=" + status + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java new file mode 100644 index 0000000..151e02b --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java @@ -0,0 +1,149 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import org.onap.aai.sa.rest.ApiUtils; + +public class ElasticSearchResultItem { + + public static final String REQUEST_URL = "REQUEST_URL"; + + private ElasticSearchOperationStatus create; + private ElasticSearchOperationStatus index; + private ElasticSearchOperationStatus delete; + + public ElasticSearchOperationStatus getCreate() { + return create; + } + + public void setCreate(ElasticSearchOperationStatus index) { + this.create = index; + } + + public ElasticSearchOperationStatus getIndex() { + return index; + } + + public void setIndex(ElasticSearchOperationStatus index) { + this.index = index; + } + + public ElasticSearchOperationStatus getDelete() { + return delete; + } + + public void setDelete(ElasticSearchOperationStatus delete) { + this.delete = delete; + } + + public String operationType() { + + if (create != null) { + return "create"; + } + if (index != null) { + return "update"; + } + if (delete != null) { + return "delete"; + } + + return "unknown"; + } + + public ElasticSearchOperationStatus operationStatus() { + + if (create != null) { + return create; + } + if (index != null) { + return index; + } + if (delete != null) { + return delete; + } + + return null; + } + + + public String toJson() { + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + sb.append("\"operation\": \"").append(operationType()).append("\", "); + + if (operationStatus().getAdditionalProperties().containsKey(REQUEST_URL)) { + sb.append("\"url\": \"").append(operationStatus().getAdditionalProperties().get(REQUEST_URL)) + .append("\", "); + } else { + sb.append("\"url\": \"") + .append(ApiUtils.buildDocumentUri(operationStatus().getIndex(), operationStatus().getId())) + .append("\", "); + } + + // We don't want to include an etag field in the response in + // the case of a delete, since that would imply that the client + // could still access that version of the file in some manner + // (which we are not supporting). + if (!operationType().equals("delete")) { + sb.append("\"etag\": \"").append(operationStatus().getVersion()).append("\", "); + } + sb.append("\"status-code\": \"").append(operationStatus().getStatus()).append("\", "); + + sb.append("\"status-message\": \""); + + if (ApiUtils.isSuccessStatusCode(operationStatus().getStatus())) { + sb.append("OK"); + } else { + // Sometimes the error object doesn't get populated, so check + // before we try to reference it... + if (operationStatus().getError() != null) { + sb.append(operationStatus().getError().getReason()); + } else { + sb.append(""); + } + } + sb.append("\""); + sb.append("}"); + + return sb.toString(); + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("ElasticSearchItemStatus ["); + if (create != null) { + sb.append("create " + create); + } else if (index != null) { + sb.append("index " + index); + } else if (delete != null) { + sb.append("delete " + index); + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java new file mode 100644 index 0000000..e846a38 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java @@ -0,0 +1,59 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +public class ElasticSearchShardStatus { + + private int total; + private int successful; + private int failed; + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public int getSuccessful() { + return successful; + } + + public void setSuccessful(int successful) { + this.successful = successful; + } + + public int getFailed() { + return failed; + } + + public void setFailed(int failed) { + this.failed = failed; + } + + @Override + public String toString() { + return "ElasticSearchShardStatus [total=" + total + ", successful=" + successful + ", failed=" + failed + "]"; + } + + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java new file mode 100644 index 0000000..7db6c4e --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.exception; + +public class DocumentStoreOperationException extends Exception { + + private static final long serialVersionUID = -7689309913743200670L; + + public enum ErrorMessage { + NO_RESPONSE_CODE( + "Failed to get the response code from the connection." + ), + SET_REQUEST_METHOD_FAILED( + "Failed to set HTTP request method to %s." + ); + private String message; + + ErrorMessage(String msg) { + this.message = msg; + } + } + + public DocumentStoreOperationException(ErrorMessage error, Exception ex, Object... args) { + super(String.format(error.message, args), ex); + } + + public DocumentStoreOperationException(String message, Exception ex) { + super(message, ex); + } + + public DocumentStoreOperationException(String message) { + super(message); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java new file mode 100644 index 0000000..ae0a3e9 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java @@ -0,0 +1,75 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; + +public class AggregationBucket { + private Object key; + + @JsonProperty("formatted-key") + private String formattedKey; + + private Number count; + + @JsonProperty("sub-aggregations") + private AggregationResult[] subAggregationResult; + + public Object getKey() { + return key; + } + + public void setKey(Object key) { + this.key = key; + } + + public String getFormattedKey() { + return formattedKey; + } + + public void setFormattedKey(String formattedKey) { + this.formattedKey = formattedKey; + } + + public Number getCount() { + return count; + } + + public void setCount(Number count) { + this.count = count; + } + + public AggregationResult[] getSubAggregationResult() { + return subAggregationResult; + } + + public void setSubAggregationResult(AggregationResult[] subAggregationResult) { + this.subAggregationResult = subAggregationResult; + } + + @Override + public String toString() { + return "AggregationBucket [key=" + key + ", formattedKey=" + formattedKey + ", count=" + count + + ", subAggregationResult=" + Arrays.toString(subAggregationResult) + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java new file mode 100644 index 0000000..923afbf --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java @@ -0,0 +1,74 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; + +public class AggregationResult { + private String name; + + private Number count; + + private AggregationBucket[] buckets; + + @JsonProperty("nested-aggregations") + private AggregationResult[] nestedAggregations; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public AggregationBucket[] getBuckets() { + return buckets; + } + + public void setBuckets(AggregationBucket[] buckets) { + this.buckets = buckets; + } + + public AggregationResult[] getNestedAggregations() { + return nestedAggregations; + } + + public void setNestedAggregations(AggregationResult[] nestedAggregations) { + this.nestedAggregations = nestedAggregations; + } + + public Number getCount() { + return count; + } + + public void setCount(Number count) { + this.count = count; + } + + @Override + public String toString() { + return "AggregationResult [name=" + name + ", count=" + count + ", buckets=" + Arrays.toString(buckets) + + ", nestedAggregations=" + Arrays.toString(nestedAggregations) + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java new file mode 100644 index 0000000..f8f3ed3 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import java.util.Arrays; + +public class AggregationResults { + private AggregationResult[] aggregations; + + public AggregationResult[] getAggregations() { + return aggregations; + } + + public void setAggregations(AggregationResult[] aggregations) { + this.aggregations = aggregations; + } + + @Override + public String toString() { + return "AggregationResults [aggregations=" + Arrays.toString(aggregations) + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java new file mode 100644 index 0000000..8b7df43 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java @@ -0,0 +1,61 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import org.json.simple.JSONObject; + +public class Document { + private String etag; + private String url; + + private JSONObject content; + + public String getEtag() { + return etag; + } + + public void setEtag(String etag) { + this.etag = etag; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public JSONObject getContent() { + return content; + } + + public void setContent(JSONObject content) { + this.content = content; + } + + @Override + public String toString() { + return "Document [etag=" + etag + ", url=" + url + "]"; + } + + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java new file mode 100644 index 0000000..9775446 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class DocumentOperationResult extends OperationResult { + private Document document; + + public Document getDocument() { + return document; + } + + public void setDocument(Document document) { + this.document = document; + } + + @Override + public String toString() { + return "DocumentOperationResult [document=" + document + "]"; + } + + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java new file mode 100644 index 0000000..aa7e720 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class ErrorResult { + + private String type; + private String reason; + + public ErrorResult(String type, String reason) { + super(); + this.type = type; + this.reason = reason; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @Override + public String toString() { + return "ErrorResponse [type=" + type + ", reason=" + reason + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java new file mode 100644 index 0000000..0d3a8bb --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class OperationResult { + + private int resultCode; + + private String failureCause; + private String resultVersion; + private String result; + private ErrorResult error; + + public int getResultCode() { + return resultCode; + } + + public void setResultCode(int resultCode) { + this.resultCode = resultCode; + } + + public String getFailureCause() { + return failureCause; + } + + public void setFailureCause(String failureCause) { + this.failureCause = failureCause; + } + + public String getResultVersion() { + return resultVersion; + } + + public void setResultVersion(String resultVersion) { + this.resultVersion = resultVersion; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public ErrorResult getError() { + return error; + } + + public void setError(ErrorResult error) { + this.error = error; + } + + @Override + public String toString() { + return "OperationResult [resultCode=" + resultCode + ", failureCause=" + failureCause + ", resultVersion=" + + resultVersion + ", result=" + result + ", error=" + error + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java new file mode 100644 index 0000000..32b1d0c --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java @@ -0,0 +1,90 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ + +package org.onap.aai.sa.searchdbabstraction.entity; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +public class OperationResultBuilder { + + public enum Type { + DOCUMENT, + SEARCH + } + + private static final String INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT = + "Internal Error: ElasticSearch operation fault occurred"; + + private OperationResult opResult; + + public OperationResultBuilder() { + opResult = new OperationResult(); + } + + public OperationResultBuilder(Type type) { + switch (type) { + case DOCUMENT: + opResult = new DocumentOperationResult(); + break; + case SEARCH: + opResult = new SearchOperationResult(); + break; + default: + opResult = new OperationResult(); + } + } + + public OperationResult build() { + return opResult; + } + + public OperationResultBuilder useDefaults() { + opResult.setResultCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + opResult.setResult(INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT); + return this; + } + + public OperationResultBuilder resultCode(int resultCode) { + opResult.setResultCode(resultCode); + return this; + } + + public OperationResultBuilder status(Status status) { + return resultCode(status.getStatusCode()); + } + + public OperationResultBuilder failureCause(String failureCause) { + opResult.setFailureCause(failureCause); + return this; + } + + public OperationResultBuilder result(String resultMsg) { + opResult.setResult(resultMsg); + return this; + } + + public OperationResultBuilder resultVersion(String resultVersion) { + opResult.setResultVersion(resultVersion); + return this; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java new file mode 100644 index 0000000..033dafe --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java @@ -0,0 +1,48 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class SearchHit { + private String score; + Document document; + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public Document getDocument() { + return document; + } + + public void setDocument(Document document) { + this.document = document; + } + + @Override + public String toString() { + return "SearchHit [score=" + score + ", document=" + document + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java new file mode 100644 index 0000000..cf4fd3a --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import java.util.Arrays; + +public class SearchHits { + private String totalHits; + private SearchHit[] hits; + + public String getTotalHits() { + return totalHits; + } + + public void setTotalHits(String totalHits) { + this.totalHits = totalHits; + } + + public SearchHit[] getHits() { + return hits; + } + + public void setHits(SearchHit[] hits) { + this.hits = hits; + } + + @Override + public String toString() { + return "SearchHits [totalHits=" + totalHits + ", hits=" + Arrays.toString(hits) + "]"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java new file mode 100644 index 0000000..6834d33 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java @@ -0,0 +1,59 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class SearchOperationResult extends OperationResult { + + private SearchHits searchResult; + private AggregationResults aggregationResult; + private SuggestHits suggestResult; + + public SearchHits getSearchResult() { + return searchResult; + } + + public SuggestHits getSuggestResult() { + return suggestResult; + } + + public AggregationResults getAggregationResult() { + return aggregationResult; + } + + public void setAggregationResult(AggregationResults aggregations) { + this.aggregationResult = aggregations; + } + + public void setSearchResult(SearchHits hits) { + this.searchResult = hits; + } + + public void setSuggestResult(SuggestHits hits) { + this.suggestResult = hits; + } + + @Override + public String toString() { + return "SearchOperationResult [searchResult=" + searchResult + ", aggregationResult=" + aggregationResult + + ", suggestResult=" + suggestResult; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java new file mode 100644 index 0000000..4ce267d --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +public class SuggestHit { + + private String score; + private String text; + Document document; + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Document getDocument() { + return document; + } + + public void setDocument(Document document) { + this.document = document; + } + + @Override + public String toString() { + return "SearchHit [text=" + text + ",score=" + score + ", document=" + document + "]"; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java new file mode 100644 index 0000000..ecc4f25 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.entity; + +import java.util.Arrays; + +public class SuggestHits { + + private String totalHits; + private SuggestHit[] hits; + + public String getTotalHits() { + return totalHits; + } + + public void setTotalHits(String totalHits) { + this.totalHits = totalHits; + } + + public SuggestHit[] getHits() { + return hits; + } + + public void setHits(SuggestHit[] hits) { + this.hits = hits; + } + + @Override + public String toString() { + return "SuggestHit [totalHits=" + totalHits + ", hits=" + Arrays.toString(hits) + "]"; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java new file mode 100644 index 0000000..d38de2a --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java @@ -0,0 +1,182 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum SearchDbMsgs implements LogMessageEnum { + + /** + * Arguments: None + */ + SERVICE_STARTED, + + /** + * Arguments: {0} = url + */ + ELASTIC_SEARCH_CONNECTION_ATTEMPT, + + /** + * Arguments: {0} = url + */ + ELASTIC_SEARCH_CONNECTION_SUCCESS, + + /** + * Arguments: {0} = url {1} = failure cause + */ + ELASTIC_SEARCH_CONNECTION_FAILURE, + + /** + * Arguments: {0} = Filter configuration file. {1} = Failure cause. + */ + FILTERS_CONFIG_FAILURE, + + /** + * Arguments: {0} = Analysys configuration file. {1} = Failure case. + */ + ANALYSYS_CONFIG_FAILURE, + + /** + * Arguments: {0} = Index name + */ + CREATED_INDEX, + + /** + * Arguments: {0} = Index name {1} = Document type + */ + CREATE_INDEX_TIME, + + /** + * Arguments: {0} = Index name + */ + DELETED_INDEX, + + /** + * Arguments: {0} = Index name + */ + DELETE_INDEX_TIME, + + /** + * Arguments: {0} = Index name + */ + CHECK_INDEX_TIME, + + /** + * Arguments: {0} = Index name + */ + CREATE_DOCUMENT_TIME, + + /** + * Arguments: {0} = Index name {1} = Document id + */ + UPDATE_DOCUMENT_TIME, + + /** + * Arguments: {0} = Index name {1} = Document id + */ + DELETE_DOCUMENT_TIME, + + /** + * Arguments: {0} = Index name {1} = Document id + */ + GET_DOCUMENT_TIME, + + /** + * Arguments: {0} = Index name {1} = Query string + */ + QUERY_DOCUMENT_TIME, + + /** + * Arguments: + */ + BULK_OPERATIONS_TIME, + + /** + * Arguments: + */ + PROCESSED_BULK_OPERATIONS, + + /** + * Arguments: {0} = Event {1} = Result + */ + PROCESS_EVENT, + + /** + * Arguments: {0} = URL. + */ + PROCESS_INLINE_QUERY, + + /** + * Arguments {0} - Operation type (GET or POST) {1} - URL. + */ + PROCESS_PAYLOAD_QUERY, + + /** + * Arguments: {0} = Index {1} = Error + */ + INDEX_CREATE_FAILURE, + + /** + * Arguments: {0} = Index name {1} = Error cause + */ + INDEX_DELETE_FAILURE, + + /** + * Arguments: {0} = Failure cause. + */ + GET_ANALYZERS_FAILURE, + + /** + * Arguments: {0} = Failure cause. + */ + BULK_OPERATION_FAILURE, + + /** + * Arguments: {0} = Method {1} = Exception + */ + EXCEPTION_DURING_METHOD_CALL, + + /** + * Received request {0} {1} from {2}. Sending response: {3} + * + *

+ * Arguments: {0} = operation {1} = target URL {2} = source {3} = response code + */ + PROCESS_REST_REQUEST, + + STARTUP_EXCEPTION + /** + * Exception encountered during startup of search service: {0} + * + *

+ * Arguments: {0} = exception + */ + ; + + /** + * Load message bundle (SearchDbMsgs.properties file) + */ + static { + EELFResourceManager.loadMessageBundle("logging/SearchDbMsgs"); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java new file mode 100644 index 0000000..29be5ea --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java @@ -0,0 +1,75 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * This is the common parent from which all aggregation types inherit. It defines the common fields that all + * aggregations must include. + */ +public abstract class AbstractAggregation { + + /** + * The name of the field to apply the aggregation against. + */ + protected String field; + + /** + * Optionally allows the number of buckets for the aggregation to be specified. + */ + protected Integer size; + + /** + * Optionally sets the minimum number of matches that must occur before a particular bucket is included in the + * aggregation result. + */ + @JsonProperty("min-threshold") + protected Integer minThreshold; + + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } + + public Integer getMinThreshold() { + return minThreshold; + } + + public void setMinThreshold(Integer minThreshold) { + this.minThreshold = minThreshold; + } + + public abstract String toElasticSearch(); + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java new file mode 100644 index 0000000..84f0e9e --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java @@ -0,0 +1,61 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Aggregation { + private String name; + + @JsonProperty("aggregation") + private AggregationStatement aggregation; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public AggregationStatement getStatement() { + return aggregation; + } + + public void setStatement(AggregationStatement aggregation) { + this.aggregation = aggregation; + } + + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + sb.append("\""); + sb.append(name); + sb.append("\": "); + sb.append(aggregation.toElasticSearch()); + return sb.toString(); + } + + @Override + public String toString() { + return "{name: " + name + ", aggregation: " + aggregation.toString(); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java new file mode 100644 index 0000000..94a091d --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java @@ -0,0 +1,173 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; + +public class AggregationStatement { + + @JsonProperty("group-by") + private GroupByAggregation groupBy; + + @JsonProperty("date-range") + private DateRangeAggregation dateRange; + + @JsonProperty("date-histogram") + private DateHistogramAggregation dateHist; + + @JsonProperty("nested") + private Aggregation[] nested; + + @JsonProperty("sub-aggregations") + private Aggregation[] subAggregations; + + public GroupByAggregation getGroupBy() { + return groupBy; + } + + public void setGroupBy(GroupByAggregation groupBy) { + this.groupBy = groupBy; + } + + public DateRangeAggregation getDateRange() { + return dateRange; + } + + public void setDateRange(DateRangeAggregation dateRange) { + this.dateRange = dateRange; + } + + public DateHistogramAggregation getDateHist() { + return dateHist; + } + + public void setDateHist(DateHistogramAggregation dateHist) { + this.dateHist = dateHist; + } + + public Aggregation[] getNested() { + return nested; + } + + public void setNested(Aggregation[] nested) { + this.nested = nested; + } + + public Aggregation[] getSubAggregations() { + return subAggregations; + } + + public void setSubAggregations(Aggregation[] subAggregations) { + this.subAggregations = subAggregations; + } + + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + if (nested != null && nested.length > 0) { + sb.append("\"nested\": {\"path\": \""); + if (nested[0].getStatement() != null) { + sb.append(nested[0].getStatement().getNestedPath()); + } + sb.append("\"}, \"aggs\": {"); + for (int i = 0; i < nested.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(nested[i].toElasticSearch()); + } + + sb.append("}"); + } else { + if (groupBy != null) { + sb.append(groupBy.toElasticSearch()); + } else if (dateRange != null) { + sb.append(dateRange.toElasticSearch()); + } else if (dateHist != null) { + sb.append(dateHist.toElasticSearch()); + } + + if (subAggregations != null && subAggregations.length > 0) { + sb.append(", \"aggs\": {"); + for (int i = 0; i < subAggregations.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(subAggregations[i].toElasticSearch()); + } + sb.append("}"); + } + } + + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + if (nested != null) { + sb.append("{nested: "); + sb.append(Arrays.toString(nested)); + } else if (groupBy != null) { + sb.append(groupBy.toString()); + } else if (dateHist != null) { + sb.append(dateHist.toString()); + } else if (dateRange != null) { + sb.append(dateRange.toString()); + } + + if (subAggregations != null) { + sb.append(", sub-aggregations: "); + sb.append(Arrays.toString(subAggregations)); + } + + sb.append("}"); + + return sb.toString(); + } + + public String getNestedPath() { + String path = null; + String fieldName = null; + + if (groupBy != null) { + fieldName = groupBy.getField(); + } else if (dateRange != null) { + fieldName = dateRange.getField(); + } else if (dateHist != null) { + fieldName = dateHist.getField(); + } + + if (fieldName != null && fieldName.contains(".")) { + // we have nested field + path = fieldName.substring(0, fieldName.indexOf(".")); + } + + return path; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java new file mode 100644 index 0000000..96bb25d --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java @@ -0,0 +1,117 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An example of elasticsearch date_histogram aggregation: + * + *

+ * + *

+ * {
+ *    "aggs": {
+ *        "my_group": {
+ *            "date_histogram" : {
+ *               "field" : "date",
+ *               "interval" : "month"
+ *           }
+ *        }
+ *    }
+ * }
+ * 
+ */ + +public class DateHistogramAggregation extends AbstractAggregation { + + private String interval; + + private String format; + + @JsonProperty("time-zone") + private String timeZone; + + + public String getInterval() { + return interval; + } + + public void setInterval(String interval) { + this.interval = interval; + } + + public String getTimeZone() { + return timeZone; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public void setTimeZone(String timeZone) { + this.timeZone = timeZone; + } + + @Override + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + + sb.append("\"date_histogram\": {\"field\": \""); + sb.append(field); + sb.append("\""); + if (interval != null) { + sb.append(", \"interval\": \""); + sb.append(interval); + sb.append("\""); + } + if (format != null) { + sb.append(", \"format\": \""); + sb.append(format); + sb.append("\""); + } + if (timeZone != null) { + sb.append(", \"time_zone\": \""); + sb.append(timeZone); + sb.append("\""); + } + if (size != null) { + sb.append(", \"size\": "); + sb.append(size); + } + if (minThreshold != null) { + sb.append(", \"min_doc_count\": ").append(minThreshold); + } + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + return "DateHistogramAggregation: [field=" + field + ", interval=" + interval + ", format=" + format + + ", timeZone=" + timeZone + ", size=" + size + " minThreshold=" + minThreshold; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java new file mode 100644 index 0000000..cd49ee7 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java @@ -0,0 +1,115 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * This class represents the ranges specification in an date_range statement. + *

+ * The expected JSON structure for a ranges is as follows: + *

+ * + *

+ * {
+ *  "from": 
+ * }
+ * 
+ *

+ * or + *

+ * + *

+ * {
+ *  "to": 
+ * }
+ * 
+ *

+ * or + *

+ * + *

+ * {
+ *  "from": ,
+ *  "to": 
+ * }
+ * 
+ * + * @author sye + */ +public class DateRange { + + @JsonProperty("from") + private String fromDate; + + @JsonProperty("to") + private String toDate; + + public String getFromDate() { + return fromDate; + } + + public void setFromDate(String fromDate) { + this.fromDate = fromDate; + } + + public String getToDate() { + return toDate; + } + + public void setToDate(String toDate) { + this.toDate = toDate; + } + + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + if (fromDate != null) { + sb.append("\"from\": \""); + sb.append(fromDate); + sb.append("\""); + } + + if (toDate != null) { + if (fromDate != null) { + sb.append(", \"to\": \""); + sb.append(toDate); + sb.append("\""); + } else { + sb.append("\"to\": \""); + sb.append(toDate); + sb.append("\""); + } + } + + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + return "{from: " + fromDate + ", to: " + toDate + "}"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java new file mode 100644 index 0000000..a4e0cc2 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java @@ -0,0 +1,130 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An example of a date_range aggregation: + * + *

+ * + *

+ * {
+ *    "aggs": {
+ *        "range": {
+ *            "date_range": {
+ *                "field": "date",
+ *                "format": "MM-yyy",
+ *                "ranges": [
+ *                    { "to": "now-10M/M" },
+ *                    { "from": "now-10M/M" }
+ *                ]
+ *            }
+ *        }
+ *    }
+ * }
+ * 
+ * + * @author sye + */ +public class DateRangeAggregation extends AbstractAggregation { + + private String format; + + @JsonProperty("ranges") + private DateRange[] dateRanges; + + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public DateRange[] getDateRanges() { + return dateRanges; + } + + public void setDateRanges(DateRange[] dateRanges) { + this.dateRanges = dateRanges; + } + + @Override + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + + sb.append("\"date_range\": {\"field\": \""); + sb.append(field); + sb.append("\""); + + if (format != null) { + sb.append(", \"format\": \""); + sb.append(format); + sb.append("\""); + } + + if (dateRanges != null && dateRanges.length > 0) { + sb.append(", \"ranges\": ["); + + for (int i = 0; i < dateRanges.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(dateRanges[i].toElasticSearch()); + } + + sb.append("]"); + } + + if (size != null) { + sb.append(", \"size\": "); + sb.append(size); + } + + if (minThreshold != null) { + sb.append(", \"min_doc_count\": ").append(minThreshold); + } + + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("date-range: {field: " + field + ", format: " + format + ", size: " + size + ", minThreshold: " + + minThreshold + "ranges: ["); + for (int i = 0; i < dateRanges.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(dateRanges[i].toString()); + } + sb.append("]"); + + return sb.toString(); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java new file mode 100644 index 0000000..134c660 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java @@ -0,0 +1,183 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents the filter stanza in a search statement. + * + *

+ * The expected JSON structure for a filter stanza is as follows: + * + *

+ * {
+ *     "filter": {
+ *        "all": [ {query structure}, {query structure}, ... {query structure} ],
+ *        "any": [ {query structure}, {query structure}, ... {query structure} ]
+ *     }
+ * }
+ * 
+ */ +public class Filter { + + /** + * All queries in this list must evaluate to true for the filter to pass. + */ + private QueryStatement[] all; + + /** + * Any one of the queries in this list must evaluate to true for the filter to pass. + */ + private QueryStatement[] any; + + + public QueryStatement[] getAll() { + return all; + } + + public void setAll(QueryStatement[] all) { + this.all = all; + } + + public QueryStatement[] getAny() { + return any; + } + + public void setAny(QueryStatement[] any) { + this.any = any; + } + + /** + * This method returns a string which represents this filter in syntax that is understandable by ElasticSearch and + * is suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + List notMatchQueries = new ArrayList<>(); + sb.append("{"); + sb.append("\"bool\": {"); + + // Add the queries from our 'all' list. + int matchQueriesCount = 0; + int notMatchQueriesCount = 0; + if (all != null) { + sb.append("\"must\": ["); + + for (QueryStatement query : all) { + if (matchQueriesCount > 0) { + sb.append(", "); + } + + if (query.isNotMatch()) { + notMatchQueries.add(query); + } else { + sb.append(query.toElasticSearch()); + matchQueriesCount++; + } + } + sb.append("],"); + + + sb.append("\"must_not\": ["); + for (QueryStatement query : notMatchQueries) { + if (notMatchQueriesCount > 0) { + sb.append(", "); + } + sb.append(query.toElasticSearch()); + notMatchQueriesCount++; + } + sb.append("]"); + } + + // Add the queries from our 'any' list. + notMatchQueries.clear(); + if (any != null) { + if (all != null) { + sb.append(","); + } + sb.append("\"should\": ["); + + matchQueriesCount = 0; + for (QueryStatement query : any) { + if (matchQueriesCount > 0) { + sb.append(", "); + } + + if (query.isNotMatch()) { + notMatchQueries.add(query); + } else { + sb.append(query.toElasticSearch()); + matchQueriesCount++; + } + } + sb.append("],"); + + notMatchQueriesCount = 0; + sb.append("\"must_not\": ["); + for (QueryStatement query : notMatchQueries) { + if (notMatchQueriesCount > 0) { + sb.append(", "); + } + sb.append(query.toElasticSearch()); + notMatchQueriesCount++; + } + sb.append("]"); + } + sb.append("}"); + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + sb.append("all: ["); + if (all != null) { + for (QueryStatement query : all) { + sb.append(query.toString()); + } + } + sb.append("], "); + + sb.append("any: ["); + if (any != null) { + for (QueryStatement query : any) { + sb.append(query.toString()); + } + } + sb.append("] "); + + sb.append("}"); + + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java new file mode 100644 index 0000000..69730d2 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +/** + * An example of a date_range aggregation: + * + *

+ * + *

+ * {
+ *    "aggs": {
+ *        "my_group": {
+ *            "term": {
+ *                "field": "group"
+ *            }
+ *        }
+ *    }
+ * }
+ * 
+ * + * @author sye + */ +public class GroupByAggregation extends AbstractAggregation { + + @Override + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + + sb.append("\"terms\": {\"field\": \""); + sb.append(field); + sb.append("\""); + if (size != null) { + sb.append(", \"size\": "); + sb.append(size); + } + + if (minThreshold != null) { + sb.append(", \"min_doc_count\": ").append(minThreshold); + } + + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + return "{group-by: {field: " + field + ", size: " + size + " minThreshold: " + minThreshold + "}}"; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java new file mode 100644 index 0000000..19bc250 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java @@ -0,0 +1,120 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * This class represents a simple parsed query statement. + * + *

+ * A 'parsed query' specifies a document field to inspect and a query string which will be parsed by the document store + * to generate the exact query to be performed. + * + *

+ * The query string will be tokenized into 'terms' and 'operators' where: + * + *

+ * Terms may be any of the following: + *

    + *
  • single words
  • + *
  • exact phrases (denoted by surrounding the phrase with '"' characters)
  • + *
  • regular expressions (denoted by surrounding the phrase with '/' characters)
  • + *
+ * + *

+ * Operators may be any of the following: + *

    + *
  • + -- The term to the right of the operator MUST be present to produce a match.
  • + *
  • - -- The term to the right of the operator MUST NOT be present to produce a match.
  • + *
  • AND -- Both the terms to the left and right of the operator MUST be present to produce a match.
  • + *
  • OR -- Either the term to the left or right of the operator MUST be present to produce a match.
  • + *
  • NOT -- The term to the right of the operator MUST NOT be present to produce a match.
  • + *
+ * + *

+ * The expected JSON structure for a parsed query is as follows: + * + *

+ *     {
+ *         "parsed-query": {
+ *             "field": "fieldname",
+ *             "query-string": "string"
+ *         }
+ *     }
+ * 
+ */ +public class ParsedQuery { + + /** + * The name of the field which the query is to be applied to. + */ + private String field; + + /** + * The string to be parsed to generate the full query. + */ + @JsonProperty("query-string") + private String queryString; + + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public String getQueryString() { + return queryString; + } + + public void setQueryString(String queryString) { + this.queryString = queryString; + } + + + /** + * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is + * suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + sb.append("\"query_string\": {"); + sb.append("\"default_field\": \"").append(field).append("\", "); + sb.append("\"query\": \"").append(queryString).append("\""); + sb.append("}"); + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + return "{field:" + field + ", query-string: '" + queryString + "'}"; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java new file mode 100644 index 0000000..ee8ffdc --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java @@ -0,0 +1,90 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +public class Query { + + private QueryStatement may; + private QueryStatement must; + + public QueryStatement getMay() { + return may; + } + + public void setMay(QueryStatement may) { + this.may = may; + } + + public QueryStatement getMust() { + return must; + } + + public void setMust(QueryStatement must) { + this.must = must; + } + + public QueryStatement getQueryStatement() { + if (isMust()) { + return must; + } else if (isMay()) { + return may; + } else { + return null; + } + } + + public boolean isMust() { + return must != null; + } + + public boolean isMay() { + return may != null; + } + + public String toElasticSearch() { + + if (isMust()) { + return must.toElasticSearch(); + } else if (isMay()) { + return may.toElasticSearch(); + } else { + return ""; // throw an exception? + } + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append("Query:["); + if (isMust()) { + sb.append("must: ").append(must.toString()); + } else if (isMay()) { + sb.append("may: ").append(may.toString()); + } else { + sb.append("INVALID"); + } + sb.append("]"); + + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java new file mode 100644 index 0000000..7764051 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java @@ -0,0 +1,138 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class QueryStatement { + + private TermQuery match; + + @JsonProperty("not-match") + private TermQuery notMatch; + + @JsonProperty("parsed-query") + private ParsedQuery parsedQuery; + + private RangeQuery range; + + public TermQuery getMatch() { + return match; + } + + public void setMatch(TermQuery match) { + this.match = match; + } + + public TermQuery getNotMatch() { + return notMatch; + } + + public void setNotMatch(TermQuery notMatch) { + this.notMatch = notMatch; + } + + public ParsedQuery getParsedQuery() { + return parsedQuery; + } + + public void setParsedQuery(ParsedQuery parsedQuery) { + this.parsedQuery = parsedQuery; + } + + public RangeQuery getRange() { + return range; + } + + public void setRange(RangeQuery range) { + this.range = range; + } + + public boolean isNotMatch() { + return (notMatch != null); + } + + public String toElasticSearch() { + + if (match != null) { + return match.toElasticSearch(); + + } else if (notMatch != null) { + return notMatch.toElasticSearch(); + + } else if (parsedQuery != null) { + + // We need some special wrapping if this query is against a nested field. + if (fieldIsNested(parsedQuery.getField())) { + return "{\"nested\": { \"path\": \"" + pathForNestedField(parsedQuery.getField()) + "\", \"query\": " + + parsedQuery.toElasticSearch() + "}}"; + } else { + return parsedQuery.toElasticSearch(); + } + + } else if (range != null) { + + // We need some special wrapping if this query is against a nested field. + if (fieldIsNested(range.getField())) { + return "{\"nested\": { \"path\": \"" + pathForNestedField(range.getField()) + "\", \"query\": " + + range.toElasticSearch() + "}}"; + } else { + return range.toElasticSearch(); + } + + } else { + // throw an exception? + return null; + } + } + + private boolean fieldIsNested(String field) { + return field.contains("."); + } + + private String pathForNestedField(String field) { + int index = field.lastIndexOf('.'); + return field.substring(0, index); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + if (match != null) { + sb.append("TERM QUERY: { match: {").append(match.toString()).append("}}"); + } else if (notMatch != null) { + sb.append("TERM QUERY: { not-match: {").append(match.toString()).append("}}"); + } else if (parsedQuery != null) { + sb.append("PARSED QUERY: { ").append(parsedQuery.toString()).append("}"); + } else if (range != null) { + sb.append("RANGE QUERY: { ").append(range.toString()).append("}"); + } else { + sb.append("UNDEFINED"); + } + + sb.append("}"); + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java new file mode 100644 index 0000000..60cc9e6 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java @@ -0,0 +1,336 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * This class represents a simple range query. + * + *

+ * A range query is composed of one or more operator/value pairs which define the upper and lower bounds of the range, + * and a field to apply the query to. + * + *

+ * Operators may be one of the following: + *

    + *
  • gt - Greater than.
  • + *
  • gte - Greater than or equal to.
  • + *
  • lt - Less than.
  • + *
  • lte - Less than or equal to.
  • + *
+ * Values may be either numeric values (Integer or Double) or Strings representing dates. + * + *

+ * The following examples illustrate a couple of variants of the range query: + * + *

+ * + *

+ *     // A simple numeric range query:
+ *     {
+ *         "range": {
+ *             "field": "fieldname",
+ *             "gte": 5,
+ *             "lte": 10
+ *         }
+ *     }
+ *
+ *     // A simple date range query:
+ *     {
+ *         "range": {
+ *             "field": "fieldname",
+ *             "gt": "2016-10-06T00:00:00.558+03:00",
+ *             "lt": "2016-10-06T23:59:59.558+03:00"
+ *         }
+ *     }
+ * 
+ */ +public class RangeQuery { + + /** + * The name of the field to apply the range query against. + */ + private String field; + + /** + * The value of the field must be greater than this value to be a match.
+ * NOTE: Only one of 'gt' or 'gte' should be set on any single {@link RangeQuery} instance. + */ + private Object gt; + + /** + * The value of the field must be greater than or equal to this value to be a match.
+ * NOTE: Only one of 'gt' or 'gte' should be set on any single {@link RangeQuery} instance. + */ + private Object gte; + + /** + * The value of the field must be less than this value to be a match.
+ * NOTE: Only one of 'lt' or 'lte' should be set on any single {@link RangeQuery} instance. + */ + private Object lt; + + /** + * The value of the field must be less than or equal to than this value to be a match.
+ * NOTE: Only one of 'lt' or 'lte' should be set on any single {@link RangeQuery} instance. + */ + private Object lte; + + private String format; + + @JsonProperty("time-zone") + private String timeZone; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public Object getGt() { + return gt; + } + + public void setGt(Object gt) { + + // It does not make sense to assign a value to both the 'greater than' + // and 'greater than or equal' operations, so make sure we are not + // trying to do that. + if (gte == null) { + + // Make sure that we are not trying to mix both numeric and date + // type values in the same queries. + if (((lt != null) && !typesMatch(gt, lt)) || ((lte != null) && !typesMatch(gt, lte))) { + throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); + } + + // If we made it here, then we're all good. Store the value. + this.gt = gt; + } else { + throw new IllegalArgumentException("Cannot assign both 'gt' and 'gte' fields in the same ranged query"); + } + } + + + public Object getGte() { + return gte; + } + + public void setGte(Object gte) { + + // It does not make sense to assign a value to both the 'greater than' + // and 'greater than or equal' operations, so make sure we are not + // trying to do that. + if (gt == null) { + + // Make sure that we are not trying to mix both numeric and date + // type values in the same queries. + if (((lt != null) && !typesMatch(gte, lt)) || ((lte != null) && !typesMatch(gte, lte))) { + throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); + } + + // If we made it here, then we're all good. Store the value. + this.gte = gte; + + } else { + throw new IllegalArgumentException("Cannot assign both 'gt' and 'gte' fields in the same ranged query"); + } + } + + public Object getLt() { + return lt; + } + + public void setLt(Object lt) { + + // It does not make sense to assign a value to both the 'less than' + // and 'less than or equal' operations, so make sure we are not + // trying to do that. + if (lte == null) { + + // Make sure that we are not trying to mix both numeric and date + // type values in the same queries. + if (((gt != null) && !typesMatch(lt, gt)) || ((gte != null) && !typesMatch(lt, gte))) { + throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); + } + + // If we made it here, then we're all good. Store the value. + + this.lt = lt; + } else { + throw new IllegalArgumentException("Cannot assign both 'lt' and 'lte' fields in the same ranged query"); + } + } + + public Object getLte() { + return lte; + } + + public void setLte(Object lte) { + + // It does not make sense to assign a value to both the 'greater than' + // and 'greater than or equal' operations, so make sure we are not + // trying to do that. + if (lt == null) { + + // Make sure that we are not trying to mix both numeric and date + // type values in the same queries. + if (((gt != null) && !typesMatch(lte, gt)) || ((gte != null) && !typesMatch(lte, gte))) { + throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); + } + + // If we made it here, then we're all good. Store the value. + + this.lte = lte; + } else { + throw new IllegalArgumentException("Cannot assign both 'lt' and 'lte' fields in the same ranged query"); + } + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public String getTimeZone() { + return timeZone; + } + + public void setTimeZone(String timeZone) { + this.timeZone = timeZone; + } + + /** + * This convenience method determines whether or not the supplied value needs to be enclosed in '"' characters when + * generating ElasticSearch compatible syntax. + * + * @param val - The value to check. + * @return - A string representation of the value for inclusion in an ElasticSearch syntax string. + */ + private String formatStringOrNumericVal(Object val) { + + if (val instanceof String) { + return "\"" + val.toString() + "\""; + } else { + return val.toString(); + } + } + + + /** + * This convenience method verifies that the supplied objects are of classes considered to be compatible for a + * ranged query. + * + * @param value1 - The first value to check. + * @param value2 - The second value to check. + * @return - True if the two objects are compatible for inclusion in the same ranged query, False, otherwise. + */ + boolean typesMatch(Object value1, Object value2) { + + return ((value1 instanceof String) && (value2 instanceof String)) + || (!(value1 instanceof String) && !(value2 instanceof String)); + } + + + /** + * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is + * suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + sb.append("\"range\": {"); + sb.append("\"").append(field).append("\": {"); + + // We may have one or zero of 'greater than' or 'greater + // than or equal' + boolean needComma = false; + if (gte != null) { + sb.append("\"gte\": ").append(formatStringOrNumericVal(gte)); + needComma = true; + } else if (gt != null) { + sb.append("\"gt\": ").append(formatStringOrNumericVal(gt)); + needComma = true; + } + + // We may have one or zero of 'less than' or 'less + // than or equal' + if (lte != null) { + if (needComma) { + sb.append(", "); + } + sb.append("\"lte\": ").append(formatStringOrNumericVal(lte)); + } else if (lt != null) { + if (needComma) { + sb.append(", "); + } + sb.append("\"lt\": ").append(formatStringOrNumericVal(lt)); + } + + // Append the format specifier if one was provided. + if (format != null) { + sb.append(", \"format\": \"").append(format).append("\""); + } + + // Append the time zone specifier if one was provided. + if (timeZone != null) { + sb.append(", \"time_zone\": \"").append(timeZone).append("\""); + } + + sb.append("}"); + sb.append("}"); + sb.append("}"); + + return sb.toString(); + } + + @Override + public String toString() { + + String str = "{ field: " + field + ", "; + + if (gt != null) { + str += "gt: " + gt; + } else if (gte != null) { + str += "gte: " + gte; + } + + if (lt != null) { + str += (((gt != null) || (gte != null)) ? ", " : "") + "lt: " + lt; + } else if (lte != null) { + str += (((gt != null) || (gte != null)) ? ", " : "") + "lte: " + lte; + } + + str += "}"; + + return str; + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java new file mode 100644 index 0000000..d14f8df --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java @@ -0,0 +1,319 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import org.radeox.util.logging.Logger; + +/** + * This class represents the structure of a search statement. + * + *

+ * The expected JSON structure to represent a search statement is as follows: + * + *

+ * + *

+ *     {
+ *         "results-start": int,  - Optional: index of starting point in result set.
+ *         "results-size": int,   - Optional: maximum number of documents to include in result set.
+ *
+ *         "filter": {
+ *             { filter structure - see {@link Filter} }
+ *         },
+ *
+ *         "queries": [
+ *             { query structure - see {@link QueryStatement} },
+ *             { query structure - see {@link QueryStatement} },
+ *                              .
+ *                              .
+ *             { query structure - see {@link QueryStatement} },
+ *         ],
+ *
+ *         "aggregations": [
+ *             { aggregation structure - see {@link AggregationStatement} },
+ *             { aggregation structure - see {@link AggregationStatement} },
+ *                              .
+ *                              .
+ *             { aggregation structure - see {@link AggregationStatement} },
+ *         ]
+ *     }
+ * 
+ */ +public class SearchStatement { + + /** + * Defines the filters that should be applied before running the actual queries. This is optional. + */ + private Filter filter; + + /** + * The list of queries to be applied to the document store. + */ + private Query[] queries; + + /** + * The list of aggregations to be applied to the search + */ + private Aggregation[] aggregations; + + /** + * Defines the sort criteria to apply to the query result set. This is optional. + */ + private Sort sort; + + @JsonProperty("results-start") + private Integer resultsStart; + + @JsonProperty("results-size") + private Integer size; + + public Filter getFilter() { + return filter; + } + + public void setFilter(Filter filter) { + this.filter = filter; + } + + public Query[] getQueries() { + return queries; + } + + public void setQueries(Query[] queries) { + this.queries = queries; + } + + public Sort getSort() { + return sort; + } + + public void setSort(Sort sort) { + this.sort = sort; + } + + public boolean isFiltered() { + return filter != null; + } + + public Aggregation[] getAggregations() { + return aggregations; + } + + public void setAggregations(Aggregation[] aggregations) { + this.aggregations = aggregations; + } + + public boolean hasAggregations() { + return aggregations != null && aggregations.length > 0; + } + + public Integer getFrom() { + return resultsStart; + } + + public void setFrom(Integer from) { + this.resultsStart = from; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } + + /** + * This method returns a string which represents this statement in syntax that is understandable by ElasticSearch + * and is suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + StringBuilder sb = new StringBuilder(); + List notMatchQueries = new ArrayList<>(); + List mustQueries = new ArrayList<>(); + List shouldQueries = new ArrayList<>(); + + createQueryLists(queries, mustQueries, shouldQueries, notMatchQueries); + + sb.append("{"); + + sb.append("\"version\": true,"); + + // If the client has specified an index into the results for the first + // document in the result set then include that in the ElasticSearch + // query. + if (resultsStart != null) { + sb.append("\"from\": ").append(resultsStart).append(", "); + } + + // If the client has specified a maximum number of documents to be returned + // in the result set then include that in the ElasticSearch query. + if (size != null) { + sb.append("\"size\": ").append(size).append(", "); + } + + sb.append("\"query\": {"); + sb.append("\"bool\": {"); + + sb.append("\"must\": ["); + AtomicBoolean firstQuery = new AtomicBoolean(true); + for (QueryStatement query : mustQueries) { + + if (!firstQuery.compareAndSet(true, false)) { + sb.append(", "); + } + + sb.append(query.toElasticSearch()); + } + sb.append("], "); + + sb.append("\"should\": ["); + + firstQuery = new AtomicBoolean(true); + for (QueryStatement query : shouldQueries) { + + if (!firstQuery.compareAndSet(true, false)) { + sb.append(", "); + } + + sb.append(query.toElasticSearch()); + } + + sb.append("],"); // close should list + + sb.append("\"must_not\": ["); + firstQuery.set(true); + for (QueryStatement query : notMatchQueries) { + sb.append(query.toElasticSearch()); + } + sb.append("]"); + + // Add the filter stanza, if one is required. + if (isFiltered()) { + sb.append(", \"filter\": ").append(filter.toElasticSearch()); + } + + sb.append("}"); // close bool clause + sb.append("}"); // close query clause + + // Add the sort directive, if one is required. + if (sort != null) { + sb.append(", \"sort\": ").append(sort.toElasticSearch()); + } + + // Add aggregations + if (hasAggregations()) { + sb.append(", \"aggs\": {"); + + for (int i = 0; i < aggregations.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(aggregations[i].toElasticSearch()); + } + + sb.append("}"); + } + + sb.append("}"); + + Logger.debug("Generated raw ElasticSearch query statement: " + sb.toString()); + return sb.toString(); + } + + private void createQueryLists(Query[] queries, List mustList, List mayList, + List mustNotList) { + + for (Query query : queries) { + + if (query.isMust()) { + + if (query.getQueryStatement().isNotMatch()) { + mustNotList.add(query.getQueryStatement()); + } else { + mustList.add(query.getQueryStatement()); + } + } else { + + if (query.getQueryStatement().isNotMatch()) { + mustNotList.add(query.getQueryStatement()); + } else { + mayList.add(query.getQueryStatement()); + } + } + } + } + + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append("SEARCH STATEMENT: {"); + + if (size != null) { + sb.append("from: ").append(resultsStart).append(", size: ").append(size).append(", "); + } + + if (filter != null) { + sb.append("filter: ").append(filter.toString()).append(", "); + } + + sb.append("queries: ["); + AtomicBoolean firstQuery = new AtomicBoolean(true); + if (queries != null) { + for (Query query : queries) { + + if (!firstQuery.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append(query.toString()); + } + } + sb.append("]"); + + sb.append("aggregations: ["); + firstQuery = new AtomicBoolean(true); + + if (aggregations != null) { + for (Aggregation agg : aggregations) { + + if (!firstQuery.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append(agg.toString()); + } + } + sb.append("]"); + + sb.append("]}"); + + return sb.toString(); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java new file mode 100644 index 0000000..104c4b0 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java @@ -0,0 +1,72 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +public class Sort { + + private String field; + private SortDirection order = null; + + public enum SortDirection { + ascending, + descending + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public SortDirection getOrder() { + return order; + } + + public void setOrder(SortDirection order) { + this.order = order; + } + + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{ \"").append(field).append("\": { \"order\": "); + + // If a sort order wasn't explicitly supplied, default to 'ascending'. + if (order != null) { + switch (order) { + case ascending: + sb.append("\"asc\"}}"); + break; + case descending: + sb.append("\"desc\"}}"); + break; + default: + } + } else { + sb.append("\"asc\"}}"); + } + + return sb.toString(); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java new file mode 100644 index 0000000..2002748 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java @@ -0,0 +1,93 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.radeox.util.logging.Logger; + +/** + * This class represents the structure of a search statement. + * + *

+ * The expected JSON structure to represent a Completion suggest search statement is as follows: + * + * { "suggest-vnf" : { "text" : "VNFs", "completion" : { "field" : "entity_suggest", "size": 1 } } } + */ +public class SuggestionStatement { + + @JsonProperty("results-size") + private Integer size; + + @JsonProperty("suggest-field") + private String field; + + @JsonProperty("suggest-text") + private String text; + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + /** + * This method returns a string which represents this statement in syntax that is understandable by ElasticSearch + * and is suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + sb.append("\"suggest-vnf\": {"); + sb.append("\"text\": ").append("\"" + text + "\"").append(", "); + sb.append("\"completion\": {"); + sb.append("\"field\": ").append("\"" + field + "\"").append(", "); + sb.append("\"size\": ").append(size); + sb.append("}"); + sb.append("}"); + sb.append("}"); + + Logger.debug("Generated raw ElasticSearch suggest statement: " + sb.toString()); + return sb.toString(); + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java new file mode 100644 index 0000000..b8afa7e --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java @@ -0,0 +1,342 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * This class represents a simple term query. + * + *

+ * A term query takes an operator, a field to apply the query to and a value to match against the query contents. + * + *

+ * Valid operators include: + *

    + *
  • match - Field must contain the supplied value to produce a match.
  • + *
  • not-match - Field must NOT contain the supplied value to produce a match.
  • + *
+ * The following examples illustrate the structure of a few variants of the term query: + * + *

+ * + *

+ *     // Single Field Match Query:
+ *     {
+ *         "match": {"field": "searchTags", "value": "abcd"}
+ *     }
+ *
+ *     // Single Field Not-Match query:
+ *     {
+ *         "not-match": {"field": "searchTags", "value": "efgh"}
+ *     }
+ * 
+ * + *

+ * + *

+ *     // Multi Field Match Query With A Single Value:
+ *     {
+ *         "match": {"field": "entityType searchTags", "value": "pserver"}
+ *     }
+ *
+ *     // Multi Field Match Query With Multiple Values:
+ *     {
+ *         "match": {"field": "entityType searchTags", "value": "pserver tenant"}
+ *     }
+ * 
+ */ +public class TermQuery { + + /** + * The name of the field to apply the term query to. + */ + private String field; + + /** + * The value which the field must contain in order to have a match. + */ + private Object value; + + /** + * For multi field queries only. Determines the rules for whether or not a document matches the query, as follows: + * + *

+ * "and" - At least one occurrence of every supplied value must be present in any of the supplied fields. + * + *

+ * "or" - At least one occurrence of any of the supplied values must be present in any of the supplied fields. + */ + private String operator; + + @JsonProperty("analyzer") + private String searchAnalyzer; + + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + private boolean isNumericValue() { + return ((value instanceof Integer) || (value instanceof Double)); + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public String getSearchAnalyzer() { + return searchAnalyzer; + } + + public void setSearchAnalyzer(String searchAnalyzer) { + this.searchAnalyzer = searchAnalyzer; + } + + /** + * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is + * suitable for inclusion in an ElasticSearch query string. + * + * @return - ElasticSearch syntax string. + */ + public String toElasticSearch() { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + // Are we generating a multi field query? + if (isMultiFieldQuery()) { + + // For multi field queries, we have to be careful about how we handle + // nested fields, so check to see if any of the specified fields are + // nested. + if (field.contains(".")) { + + // Build the equivalent of a multi match query across one or more nested fields. + toElasticSearchNestedMultiMatchQuery(sb); + + } else { + + // Build a real multi match query, since we don't need to worry about nested fields. + toElasticSearchMultiFieldQuery(sb); + } + } else { + + // Single field query. + + // Add the necessary wrapping if this is a query against a nested field. + if (fieldIsNested(field)) { + sb.append("{\"nested\": { \"path\": \"").append(pathForNestedField(field)).append("\", \"query\": "); + } + + // Build the query. + toElasticSearchSingleFieldQuery(sb); + + if (fieldIsNested(field)) { + sb.append("}}"); + } + } + + sb.append("}"); + + return sb.toString(); + } + + + /** + * Determines whether or not the client has specified a term query with multiple fields. + * + * @return - true if the query is referencing multiple fields, false, otherwise. + */ + private boolean isMultiFieldQuery() { + + return (field.split(" ").length > 1); + } + + + /** + * Constructs a single field term query in ElasticSearch syntax. + * + * @param sb - The string builder to assemble the query string with. + * @return - The single term query. + */ + private void toElasticSearchSingleFieldQuery(StringBuilder sb) { + + sb.append("\"term\": {\"").append(field).append("\" : "); + + // For numeric values, don't enclose the value in quotes. + if (!isNumericValue()) { + sb.append("\"").append(value).append("\""); + } else { + sb.append(value); + } + + sb.append("}"); + } + + + /** + * Constructs a multi field query in ElasticSearch syntax. + * + * @param sb - The string builder to assemble the query string with. + * @return - The multi field query. + */ + private void toElasticSearchMultiFieldQuery(StringBuilder sb) { + + sb.append("\"multi_match\": {"); + + sb.append("\"query\": \"").append(value).append("\", "); + sb.append("\"type\": \"cross_fields\","); + sb.append("\"fields\": ["); + + List fields = Arrays.asList(field.split(" ")); + AtomicBoolean firstField = new AtomicBoolean(true); + for (String f : fields) { + if (!firstField.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append("\"").append(f.trim()).append("\""); + } + sb.append("],"); + + sb.append("\"operator\": \"").append((operator != null) ? operator.toLowerCase() : "and").append("\""); + + if (searchAnalyzer != null) { + sb.append(", \"analyzer\": \"").append(searchAnalyzer).append("\""); + } + + sb.append("}"); + } + + + /** + * Constructs the equivalent of an ElasticSearch multi match query across multiple nested fields. + * + *

+ * Since ElasticSearch doesn't really let you do that, we have to be clever and construct an equivalent query using + * boolean operators to produce the same result. + * + * @param sb - The string builder to use to build the query. + */ + public void toElasticSearchNestedMultiMatchQuery(StringBuilder sb) { + + // Break out our whitespace delimited list of fields and values into a actual lists. + List fields = Arrays.asList(field.split(" ")); + List values = Arrays.asList(((String) value).split(" ")); // GDF: revisit this cast. + + sb.append("\"bool\": {"); + + if (operator != null) { + + if (operator.toLowerCase().equals("and")) { + sb.append("\"must\": ["); + } else if (operator.toLowerCase().equals("or")) { + sb.append("\"should\": ["); + } + + } else { + sb.append("\"must\": ["); + } + + AtomicBoolean firstField = new AtomicBoolean(true); + for (String f : fields) { + + if (!firstField.compareAndSet(true, false)) { + sb.append(", "); + } + + sb.append("{ "); + + // Is this a nested field? + if (fieldIsNested(f)) { + + sb.append("\"nested\": {"); + sb.append("\"path\": \"").append(pathForNestedField(f)).append("\", "); + sb.append("\"query\": "); + } + + sb.append("{\"bool\": {"); + sb.append("\"should\": ["); + + AtomicBoolean firstValue = new AtomicBoolean(true); + for (String v : values) { + if (!firstValue.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append("{\"match\": { \""); + sb.append(f).append("\": {\"query\": \"").append(v).append("\""); + + if (searchAnalyzer != null) { + sb.append(", \"analyzer\": \"").append(searchAnalyzer).append("\""); + } + sb.append("}}}"); + } + + sb.append("]"); + sb.append("}"); + + if (fieldIsNested(f)) { + sb.append("}"); + sb.append("}"); + } + + sb.append("}"); + } + + sb.append("]"); + sb.append("}"); + } + + + @Override + public String toString() { + return "field: " + field + ", value: " + value + " (" + value.getClass().getName() + ")"; + } + + public boolean fieldIsNested(String field) { + return field.contains("."); + } + + public String pathForNestedField(String field) { + int index = field.lastIndexOf('.'); + return field.substring(0, index); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java new file mode 100644 index 0000000..3c4110b --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.service; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; +import org.springframework.beans.factory.annotation.Autowired; + +public class SearchService { + static Logger logger = LoggerFactory.getInstance().getLogger(SearchService.class.getName()); + + @Autowired + private ElasticSearchConfig esConfig; + + public SearchService() { + try { + start(); + } catch (Exception e) { + logger.error(SearchDbMsgs.STARTUP_EXCEPTION, e.getLocalizedMessage()); + } + } + + protected void start() throws IOException { + Properties configProperties = new Properties(); + configProperties.load(new FileInputStream(SearchDbConstants.ES_CONFIG_FILE)); + new ElasticSearchHttpController(esConfig); + logger.info(SearchDbMsgs.SERVICE_STARTED); + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java new file mode 100644 index 0000000..b48588f --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java @@ -0,0 +1,103 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.Iterator; +import java.util.Set; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationBucket; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; + +public class AggregationParsingUtil { + + private AggregationParsingUtil() { // Do not instantiate + } + + public static AggregationResult[] parseAggregationResults(JSONObject aggregations) throws JsonProcessingException { + + // Obtain the set of aggregation names + Set keySet = aggregations.keySet(); + AggregationResult[] aggResults = new AggregationResult[keySet.size()]; + + int index = 0; + for (Iterator it = keySet.iterator(); it.hasNext();) { + String key = (String) it.next(); + AggregationResult aggResult = new AggregationResult(); + aggResult.setName(key); + + JSONObject bucketsOrNested = (JSONObject) aggregations.get(key); + Object buckets = bucketsOrNested.get("buckets"); + if (buckets == null) { + // we have a nested + Number count = (Number) bucketsOrNested.remove("doc_count"); + aggResult.setCount(count); + AggregationResult[] nestedResults = parseAggregationResults(bucketsOrNested); + aggResult.setNestedAggregations(nestedResults); + } else { + AggregationBucket[] aggBuckets = parseAggregationBuckets((JSONArray) buckets); + aggResult.setBuckets(aggBuckets); + } + + aggResults[index] = aggResult; + index++; + } + + return aggResults; + + } + + private static AggregationBucket[] parseAggregationBuckets(JSONArray buckets) throws JsonProcessingException { + AggregationBucket[] aggBuckets = new AggregationBucket[buckets.size()]; + for (int i = 0; i < buckets.size(); i++) { + AggregationBucket aggBucket = new AggregationBucket(); + JSONObject bucketContent = (JSONObject) buckets.get(i); + Object key = bucketContent.remove("key"); + aggBucket.setKey(key); + Object formatted = bucketContent.remove("key_as_string"); + if (formatted != null) { + aggBucket.setFormattedKey((String) formatted); + } + Object count = bucketContent.remove("doc_count"); + if (count != null) { + aggBucket.setCount((Number) count); + } + bucketContent.remove("from"); + bucketContent.remove("from_as_string"); + bucketContent.remove("to"); + bucketContent.remove("to_as_string"); + + + if (!bucketContent.entrySet().isEmpty()) { + // we have results from sub-aggregation + AggregationResult[] subResult = parseAggregationResults(bucketContent); + if (subResult != null) { + aggBucket.setSubAggregationResult(subResult); + } + } + aggBuckets[i] = aggBucket; + } + + return aggBuckets; + } + +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java new file mode 100644 index 0000000..ebc7ae9 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java @@ -0,0 +1,134 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.commons.io.IOUtils; +import org.onap.aai.sa.rest.DocumentFieldSchema; +import org.onap.aai.sa.rest.DocumentSchema; + +public class DocumentSchemaUtil { + + private static String dynamicCustomMapping = null; + private static final String DYNAMIC_CUSTOM_TEMPALTE_FILE = + System.getProperty("CONFIG_HOME") + File.separator + "dynamic-custom-template.json"; + + private DocumentSchemaUtil() { // Do not instantiate + } + + public static String generateDocumentMappings(String documentSchema) throws IOException { + // Unmarshal the json content into a document schema object. + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); + return generateDocumentMappings(schema); + } + + public static String generateDocumentMappings(DocumentSchema schema) throws IOException { + // Adding dynamic template to add fielddata=true to dynamic fields of type "string" + // in order to avoid aggregation queries breaking in ESv6.1.2 + if (dynamicCustomMapping == null) { + try { + dynamicCustomMapping = IOUtils.toString(new FileInputStream(DYNAMIC_CUSTOM_TEMPALTE_FILE), "UTF-8") + .replaceAll("\\s+", ""); + } catch (IOException e) { + throw new IOException( + "Dynamic Custom template configuration went wrong! Please check for the correct template file.", + e); + } + } + + // Now, generate the Elastic Search mapping json and return it. + StringBuilder sb = new StringBuilder(); + sb.append("{"); + // Adding custom mapping which adds fielddata=true to dynamic fields of type "string" + sb.append(dynamicCustomMapping != null ? dynamicCustomMapping : ""); + sb.append("\"properties\": {"); + + generateFieldMappings(schema.getFields(), sb); + + sb.append("}"); + sb.append("}"); + + return sb.toString(); + } + + + private static void generateFieldMappings(List fields, StringBuilder sb) { + + AtomicBoolean firstField = new AtomicBoolean(true); + + for (DocumentFieldSchema field : fields) { + + // If this isn't the first field in the list, prepend it with a ',' + if (!firstField.compareAndSet(true, false)) { + sb.append(", "); + } + + // Now, append the translated field contents. + generateFieldMapping(field, sb); + } + } + + private static void generateFieldMapping(DocumentFieldSchema fieldSchema, StringBuilder sb) { + + sb.append("\"").append(fieldSchema.getName()).append("\": {"); + + // The field type is mandatory. + sb.append("\"type\": \"").append(fieldSchema.getDataType()).append("\""); + + // For date type fields we may optionally supply a format specifier. + if (fieldSchema.getDataType().equals("date") && fieldSchema.getFormat() != null) { + sb.append(", \"format\": \"").append(fieldSchema.getFormat()).append("\""); + } + + // If the index field was specified, then append it. + if (fieldSchema.getSearchable() != null) { + sb.append(", \"index\": \"").append(fieldSchema.getSearchable() ? "analyzed" : "not_analyzed").append("\""); + } + + // If a search analyzer was specified, then append it. + if (fieldSchema.getSearchAnalyzer() != null) { + sb.append(", \"search_analyzer\": \"").append(fieldSchema.getSearchAnalyzer()).append("\""); + } + + // If an indexing analyzer was specified, then append it. + if (fieldSchema.getIndexAnalyzer() != null) { + sb.append(", \"analyzer\": \"").append(fieldSchema.getIndexAnalyzer()).append("\""); + } + + + if (fieldSchema.getDataType().equals("nested")) { + + sb.append(", \"properties\": {"); + generateFieldMappings(fieldSchema.getSubFields(), sb); + sb.append("}"); + } + + sb.append("}"); + } + +} + diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java new file mode 100644 index 0000000..d3dd3e1 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java @@ -0,0 +1,101 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.util; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.IOUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; + + +/** + * This class as the name suggests is to translate the payload of PUT & POST requests to ElasticSearch (ES) to its + * compatible syntax, specially compatible with ES v6 or above. + * + * For example, data type such as "string" is now replaced by "text" or "keyword". + * + * So this class will make those translations reading off from a json configuration file, therefore the configuration + * can be updated with new translations as and when required without touching the code. + * + * @author EDWINL + * + */ +public class ElasticSearchPayloadTranslator { + + private static Logger logger = + LoggerFactory.getInstance().getLogger(ElasticSearchPayloadTranslator.class.getName()); + private static final String CONFIG_DIRECTORY = System.getProperty("CONFIG_HOME"); + private static final String ES_PAYLOAD_TRANSLATION_FILE = "es-payload-translation.json"; + + private ElasticSearchPayloadTranslator() { // Do not instantiate + } + + /** + * Using JSON Path query to filter objects to translate the payload to ES compatible version The filter queries and + * the replacement attributes are configured in the es-payload-translation.json file. + * + * @param source + * @return translated payload in String + * @throws IOException + */ + public static String translateESPayload(String source) throws IOException { + logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "translateESPayload, method-params[ source=" + source + "]", + "(unknown)"); + String pathToTranslationFile = CONFIG_DIRECTORY + File.separator + ES_PAYLOAD_TRANSLATION_FILE; + + try { + JSONObject translationConfigPayload = + new JSONObject(IOUtils.toString(new FileInputStream(new File(pathToTranslationFile)), "UTF-8")); + JSONArray attrTranslations = translationConfigPayload.getJSONArray("attr-translations"); + DocumentContext payloadToTranslate = JsonPath.parse(source); + + for (Object obj : attrTranslations) { + JSONObject jsonObj = ((JSONObject) obj); + String query = jsonObj.get("query").toString(); + JSONObject attrToUpdate = (JSONObject) jsonObj.get("update"); + List> filteredObjects = payloadToTranslate.read(query); + for (Map objMap : filteredObjects) { + objMap.putAll(attrToUpdate.toMap()); + } + } + + logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, + "Payload after translation: " + payloadToTranslate.jsonString()); + return payloadToTranslate.jsonString(); + } catch (JSONException ex) { + logger.error(SearchDbMsgs.FILTERS_CONFIG_FAILURE, ex, ES_PAYLOAD_TRANSLATION_FILE, ex.getMessage()); + throw new IOException("Payload translation configuration looks corrupted. Please correct!", ex); + } catch (IOException ex) { + logger.error(SearchDbMsgs.FILTERS_CONFIG_FAILURE, ex, ES_PAYLOAD_TRANSLATION_FILE, ex.getMessage()); + throw new IOException("Error in configuring payload translation file. Please check if it exists.", ex); + } + } +} diff --git a/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java new file mode 100644 index 0000000..fd63741 --- /dev/null +++ b/search-data-service/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.util; + +public class SearchDbConstants { + + public static final String SDB_FILESEP = + (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + public static final String SDB_BUNDLECONFIG_NAME = + (System.getProperty("BUNDLECONFIG_DIR") == null) ? "bundleconfig" : System.getProperty("BUNDLECONFIG_DIR"); + + public static final String SDB_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null) + ? SDB_FILESEP + "opt" + SDB_FILESEP + "app" + SDB_FILESEP + "searchdb" + SDB_FILESEP + SDB_BUNDLECONFIG_NAME + : System.getProperty("AJSC_HOME") + SDB_FILESEP + SDB_BUNDLECONFIG_NAME; + + public static final String SDB_HOME_ETC = SDB_HOME_BUNDLECONFIG + SDB_FILESEP + "etc" + SDB_FILESEP; + public static final String SDB_CONFIG_APP_LOCATION = SDB_HOME_ETC + "appprops" + SDB_FILESEP; + + // Elastic Search related + public static final String SDB_SPECIFIC_CONFIG = (System.getProperty("CONFIG_HOME") == null) + ? SDB_CONFIG_APP_LOCATION : System.getProperty("CONFIG_HOME") + SDB_FILESEP; + public static final String ES_CONFIG_FILE = SDB_SPECIFIC_CONFIG + SDB_FILESEP + "elastic-search.properties"; + public static final String SDB_AUTH = SDB_SPECIFIC_CONFIG + "auth" + SDB_FILESEP; + public static final String SDB_AUTH_CONFIG_FILENAME = SDB_AUTH + "search_policy.json"; + public static final String SDB_FILTER_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "filter-config.json"; + public static final String SDB_ANALYSIS_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "analysis-config.json"; + public static final String SDB_SETTINGS_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "settings-config.json"; + + // Logging related + public static final String SDB_SERVICE_NAME = "SearchDataService"; + + private SearchDbConstants() { // Do not instantiate + } + +} diff --git a/search-data-service/src/main/resources/application.properties b/search-data-service/src/main/resources/application.properties new file mode 100644 index 0000000..ae8f9c3 --- /dev/null +++ b/search-data-service/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.ssl.key-store=/opt/app/search-data-service/config/auth/tomcat_keystore +server.ssl.enabled=true +server.port=9509 +server.ssl.enabled-protocols=TLSv1.1,TLSv1.2 diff --git a/search-data-service/src/main/resources/banner.txt b/search-data-service/src/main/resources/banner.txt new file mode 100644 index 0000000..117d1e4 --- /dev/null +++ b/search-data-service/src/main/resources/banner.txt @@ -0,0 +1,5 @@ + ____ _ ____ ____ _ _ _ _ _ +/ ___| ___ __ _ _ __ ___| |__ | _ \| __ ) / \ | |__ ___| |_ _ __ __ _ ___| |_(_) ___ _ __ +\___ \ / _ \/ _` | '__/ __| '_ \ _____ | | | | _ \ _____ / _ \ | '_ \/ __| __| '__/ _` |/ __| __| |/ _ \| '_ \ + ___) | __/ (_| | | | (__| | | | |_____| | |_| | |_) | |_____| / ___ \| |_) \__ \ |_| | | (_| | (__| |_| | (_) | | | | +|____/ \___|\__,_|_| \___|_| |_| |____/|____/ /_/ \_\_.__/|___/\__|_| \__,_|\___|\__|_|\___/|_| |_| diff --git a/search-data-service/src/main/resources/json/schema/analyzer.schema.json b/search-data-service/src/main/resources/json/schema/analyzer.schema.json new file mode 100644 index 0000000..7592ee9 --- /dev/null +++ b/search-data-service/src/main/resources/json/schema/analyzer.schema.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Analyzer", + "description": "The analyzer aggregates a tokenizer and multiple filters to describe how an input stream should be indexed.", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "behaviours": { + "type": "array", + "items": { + "type": "string" + } + }, + "tokenizer": { + "type": "string" + }, + "filters": { + "type": "array", + "items": { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/search-data-service/src/main/resources/json/schema/document-field.schema.json b/search-data-service/src/main/resources/json/schema/document-field.schema.json new file mode 100644 index 0000000..78d6cba --- /dev/null +++ b/search-data-service/src/main/resources/json/schema/document-field.schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Document Field Schema", + "description": "Describes the structure of a document field for storage in a document store.", + "type": "object", + "javaType": "org.onap.aai.sa.rest.DocumentFieldSchema", + "properties": { + "name": { + "type": "string" + }, + "data-type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "searchable": { + "type": "boolean" + }, + "search-analyzer": { + "type": "string" + }, + "index-analyzer": { + "type": "string" + }, + "sub-fields": { + "type": "array", + "items": { + "$ref": "document-field.schema.json" + } + } + }, + "required": [ + "name", + "data-type" + ] +} \ No newline at end of file diff --git a/search-data-service/src/main/resources/json/schema/document.schema.json b/search-data-service/src/main/resources/json/schema/document.schema.json new file mode 100644 index 0000000..bbf3e50 --- /dev/null +++ b/search-data-service/src/main/resources/json/schema/document.schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Document Schema", + "description": "Describes the structure of a document for storage in a document store.", + "type": "object", + "javaType": "org.onap.aai.sa.rest.DocumentSchema", + "properties": { + "fields": { + "type": "array", + "items": { + "$ref": "document-field.schema.json" + } + } + } +} \ No newline at end of file diff --git a/search-data-service/src/main/resources/json/schema/filter.schema.json b/search-data-service/src/main/resources/json/schema/filter.schema.json new file mode 100644 index 0000000..6d1a030 --- /dev/null +++ b/search-data-service/src/main/resources/json/schema/filter.schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Filter", + "description": "Filters accept a stream of tokens from a tokenizer and apply additional rules, possibly producing additional tokens. ", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "configuration": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/search-data-service/src/main/resources/logging/SearchDbMsgs.properties b/search-data-service/src/main/resources/logging/SearchDbMsgs.properties new file mode 100644 index 0000000..3e8de80 --- /dev/null +++ b/search-data-service/src/main/resources/logging/SearchDbMsgs.properties @@ -0,0 +1,123 @@ +#Resource key=Error Code|Message text|Resolution text|Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has at least one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## +# INFO logs +SERVICE_STARTED=\ + SDB0001I|\ + SearchDB Service started|\ + NA|\ + The SearchDB Service has been started +ELASTIC_SEARCH_CONNECTION_SUCCESS=\ + SDB0002I|\ + Successfully established connection to ElasticSearch {0}|\ + NA|\ + Successfully established connection to ElasticSearch +ELASTIC_SEARCH_CONNECTION_ATTEMPT=\ + SDB0003I|\ + Attempting to connect to ElasticSearch {0}|\ + NA|\ + An attempt is being made to establish connectivity to ElasticSearch +CREATED_INDEX=\ + SDB0019I|\ + Index with name {0} created successfully +DELETED_INDEX=\ + SDB0021I|\ + Deleted index with name {0} +PROCESSED_BULK_OPERATIONS=\ + SDB0022I|\ + Successfully processed a bulk operations request. +PROCESS_EVENT=\ + SDB0041I|\ + Processed event {0}. Result: {1} +PROCESS_INLINE_QUERY=\ + SDB0042I|\ + Processing inline query: {0} +PROCESS_PAYLOAD_QUERY=\ + SDB0043I|\ + Processing query - operation: {0} against URL: {1} +# INFO Level Metrics Logs +CREATE_INDEX_TIME=\ + SDB0020I|\ + Create index request for index {0} document type {1} +DELETE_INDEX_TIME=\ + SDB0022I|\ + Delete index request for index {0} +CREATE_DOCUMENT_TIME=\ + SDB0023|\ + Create document in index {0} +UPDATE_DOCUMENT_TIME=\ + SDB0024|\ + Update document in index {0} with id {1} +DELETE_DOCUMENT_TIME=\ + SDB0025|\ + Delete document in index {0} with id {1} +GET_DOCUMENT_TIME=\ + SDB0026|\ + Get document from index {0} with id {1} +QUERY_DOCUMENT_TIME=\ + SDB0027|\ + Query request for index {0} with query string {1} +BULK_OPERATIONS_TIME=\ + SDB0028|\ + Bulk operations request +CHECK_INDEX_TIME=\ + SDB0029|\ + Check for index {0} +# WARNING logs +INDEX_CREATE_FAILURE=\ + SDB0301W|\ + Failed to create index with index name = {0}. Cause: {1}|\ + Check cause. It is possible the index already exists.|\ + Failed to create the specified index +INDEX_DELETE_FAILURE=\ + SDB0302W|\ + Failed to delete index with index name = {0}. Cause: {1}|\ + Check cause. It is possible the index does not exist.|\ + Failed to delete the specified index +FILTERS_CONFIG_FAILURE=\ + SDB0303W|\ + Failed to read filter configuration from file {0}. Cause: {1} +ANALYSYS_CONFIG_FAILURE=\ + SDB0304W|\ + Failed to read analysis configuration from file {0}. Cause: {1} +GET_ANALYZERS_FAILURE=\ + SDB0305W|\ + Failed to get analyzer definitions. Cause: {0} +BULK_OPERATION_FAILURE=\ + SDB0306W|\ + Failed to execute bulk operations. Cause: {0} +# ERROR logs +ELASTIC_SEARCH_CONNECTION_FAILURE=\ + SDB0501E|\ + Failed to establish connection to ElasticSearch {0}. Cause: {1}|\ + Check connectivity with ElasticSearch. Ensure ElasticSearch is up and reachable.|\ + A connectivity check to ElasticSearch has failed. +EXCEPTION_DURING_METHOD_CALL=\ + SDB0502E|\ + Failed to execute method {0} due to: {1}|\ + Check error cause|\ + Method failed to execute +PROCESS_REST_REQUEST=\ + SDB0503E|\ + Received request {0} {1} from {2}. Sending response: {3} +STARTUP_EXCEPTION=\ + SDB0504E|\ + Exception encountered during startup of search service: {0} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java b/search-data-service/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java new file mode 100644 index 0000000..97e928e --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java @@ -0,0 +1,86 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.auth; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; +import org.springframework.http.HttpHeaders; + +// import javax.servlet.http.Cookie; + +public class SearchDbServiceAuthTest { + + @Mock + HttpHeaders headers; + + // @Mock + // Cookie mockedCookie; + + @Before + public void setUp() throws NoSuchFieldException, IllegalAccessException, IOException { + MockitoAnnotations.initMocks(this); + System.setProperty("AJSC_HOME", new File(".").getCanonicalPath().replace('\\', '/')); + setFinalStatic(System.getProperty("AJSC_HOME") + "/src/test/resources/json/search_policy.json"); + } + + @Test + public void testAuthUser() { + SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); + String auth = aaiAuth.authUser(headers, "user-1", "function-1"); + Assert.assertEquals(auth, "AAI_9101"); + } + + // @Test + // public void testAuthCookie_NullCookie(){ + // SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); + // Cookie cookie = null; + // Assert.assertFalse(aaiAuth.authCookie(cookie, "function-1", new StringBuilder("user-1"))); + // } + + // @Test + // public void testAuthCookie_NotNullCookie(){ + // SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); + // Cookie cookie = new Cookie ( "TestCookie", "TestValue"); + // // Cookie cookie = new Cookie ( "TestCookie", "TestValue" ); + // boolean retValue = aaiAuth.authCookie(cookie, "GET:testFunction", new StringBuilder("testuser")); + // Assert.assertTrue(retValue); + // } + + static void setFinalStatic(String fieldValue) + throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + Field configField = SearchDbConstants.class.getDeclaredField("SDB_AUTH_CONFIG_FILENAME"); + configField.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(configField, configField.getModifiers() & ~Modifier.FINAL); + + configField.set(null, fieldValue); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java new file mode 100644 index 0000000..df6ed0e --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +public class ApiUtilsTest { + + @Test + public void testHTTPStatusConversion() { + assertThat(ApiUtils.getHttpStatusString(201), is(equalTo("Created"))); + assertThat(ApiUtils.getHttpStatusString(207), is(equalTo("Multi-Status"))); + assertThat(ApiUtils.getHttpStatusString(9999), is(equalTo("Unknown"))); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java new file mode 100644 index 0000000..fcc5b77 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java @@ -0,0 +1,86 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.File; +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + + +/** + * This suite of tests validates the behaviour of the bulk operations REST end point. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = org.onap.aai.sa.Application.class) +@AutoConfigureMockMvc +public class BulkApiTest { + + private final String TOP_URI = "/test/bulk"; + + @Autowired + private MockMvc mockMvc; + + @Test + public void authenticationFailureTest() throws Exception { + + this.mockMvc + .perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON) + .content(SearchServiceApiHarness.FAIL_AUTHENTICATION_TRIGGER)) + .andExpect(status().isForbidden()); + } + + + /** + * This test validates that properly constructed json payloads are correctly validated and that improperly + * contructed payloads will be rejected with the appropriate response code returned to the client. + * + * @throws IOException + */ + @Test + public void payloadValidationTest() throws Exception { + + // Post a request to the bulk operations endpoint with a valid + // operations list payload. + File validBulkOpsFile = new File("src/test/resources/json/bulk-ops-valid.json"); + String validPayloadStr = TestUtils.readFileToString(validBulkOpsFile); + + // Validate that the payload is accepted as expected. + this.mockMvc.perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON).content(validPayloadStr)) + .andExpect(status().isOk()); + + // Post a request to the bulk operations endpoint with an invalid + // operations list payload. + File inValidBulkOpsFile = new File("src/test/resources/json/bulk-ops-invalid.json"); + String inValidPayloadStr = TestUtils.readFileToString(inValidBulkOpsFile); + this.mockMvc.perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON).content(inValidPayloadStr)) + .andExpect(status().isBadRequest()); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java new file mode 100644 index 0000000..7d784d1 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java @@ -0,0 +1,149 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class BulkRequestTest { + + @Test + public void testBulkRequest_Delete() { + BulkRequest request = new BulkRequest(); + BulkOperation operation = new BulkOperation(); + Document document = new Document(); + BulkMetaData metaData = getMetaData(); + operation.setMetaData(metaData); + operation.setDocument(document); + Assert.assertNotNull(operation.getDocument()); + Assert.assertNotNull(operation.getMetaData()); + Assert.assertNotNull(operation.toString()); + + request.setDelete(operation); + Assert.assertNotNull(request.getDelete()); + Assert.assertEquals(operation, request.getOperation()); + Assert.assertEquals(BulkRequest.OperationType.DELETE, request.getOperationType()); + Assert.assertTrue(request.toString().contains("delete:")); + + + } + + @Test + public void testBulkRequest_Update() { + BulkRequest request = new BulkRequest(); + BulkOperation operation = new BulkOperation(); + Document document = new Document(); + BulkMetaData metaData = getMetaData(); + operation.setMetaData(metaData); + operation.setDocument(document); + Assert.assertNotNull(operation.getDocument()); + Assert.assertNotNull(operation.getMetaData()); + Assert.assertNotNull(operation.toString()); + + request.setUpdate(operation); + Assert.assertNotNull(request.getUpdate()); + Assert.assertEquals(operation, request.getOperation()); + Assert.assertEquals(BulkRequest.OperationType.UPDATE, request.getOperationType()); + Assert.assertTrue(request.toString().contains("update:")); + + } + + @Test + public void testBulkRequest_Create() { + BulkRequest request = new BulkRequest(); + BulkOperation operation = new BulkOperation(); + Document document = new Document(); + BulkMetaData metaData = getMetaData(); + operation.setMetaData(metaData); + operation.setDocument(document); + Assert.assertNotNull(operation.getDocument()); + Assert.assertNotNull(operation.getMetaData()); + Assert.assertNotNull(operation.toString()); + + request.setCreate(operation); + Assert.assertNotNull(request.getCreate()); + Assert.assertEquals(operation, request.getOperation()); + Assert.assertEquals(BulkRequest.OperationType.CREATE, request.getOperationType()); + Assert.assertTrue(request.toString().contains("create:")); + + } + + @Test + public void testBulkRequest_Undefined() { + BulkRequest request = new BulkRequest(); + Assert.assertNull(request.getOperation()); + Assert.assertNull(request.getOperationType()); + Assert.assertEquals("UNDEFINED", request.toString()); + } + + @Test + public void testGetIndex() { + BulkRequest request = new BulkRequest(); + BulkOperation operation = new BulkOperation(); + BulkMetaData metaData = new BulkMetaData(); + metaData.setUrl("/test/indexes/index1"); + operation.setMetaData(metaData); + request.setCreate(operation); + String index = request.getIndex(); + Assert.assertEquals(index, "index1"); + } + + @Test + public void testGetId() { + BulkRequest request = new BulkRequest(); + BulkOperation operation = new BulkOperation(); + BulkMetaData metaData = new BulkMetaData(); + metaData.setUrl("/test/documents/document1"); + operation.setMetaData(metaData); + request.setCreate(operation); + String index = request.getId(); + Assert.assertEquals(index, "document1"); + } + + @Test + public void testApiUtils() { + Assert.assertEquals("services/search-data-service/v1/search/indexes/index1", ApiUtils.buildIndexUri("index1")); + Assert.assertEquals("services/search-data-service/v1/search/indexes/index1/documents/document1", + ApiUtils.buildDocumentUri("index1", "document1")); + Assert.assertTrue(ApiUtils.validateIndexUri("services/search-data-service/v1/search/indexes/index1")); + Assert.assertTrue(ApiUtils.validateDocumentUri( + "services/search-data-service/v1/search/indexes/index1/documents/document1", true)); + Assert.assertTrue(ApiUtils.validateDocumentUri( + "services/search-data-service/v1/search/indexes/index1/documents/document1", false)); + } + + private BulkMetaData getMetaData() { + BulkMetaData metaData = new BulkMetaData(); + metaData.setUrl("http://127.0.0.1"); + metaData.setEtag("etag-1"); + Assert.assertEquals(metaData.getUrl(), "http://127.0.0.1"); + Assert.assertEquals(metaData.getEtag(), "etag-1"); + Assert.assertNotNull(metaData.toString()); + return metaData; + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java new file mode 100644 index 0000000..865f981 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java @@ -0,0 +1,206 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; + +import java.io.IOException; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class DocumentApiTest { + + private static final String INDEXES_URI = "/test/indexes/"; + private static final String DOCUMENT_URI = "documents/"; + + private static final String SEARCH_URI = "query/"; + private static final String INDEX_NAME = "test-index"; + private static final String DOC_ID = "test-1"; + private static final String SIMPLE_QUERY = + "\"parsed-query\": {\"my-field\": \"something\", \"query-string\": \"string\"}"; + private static final String COMPLEX_QUERY = "{" + "\"filter\": {" + "\"all\": [" + + "{\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}" + "]" + "}," + "\"queries\": [" + + "{\"may\": {\"parsed-query\": {\"field\": \"searchTags\", \"query-string\": \"b\"}}}" + "]" + "}"; + + private static final String CREATE_JSON_CONTENT = "creation content"; + + @Autowired + private MockMvc mockMvc; + + /** + * This test validates the behaviour of the 'Create Document' POST request endpoint. + * + * @throws IOException + * @throws ParseException + */ + @Test + public void createDocumentTest() throws Exception { + + MvcResult result = this.mockMvc.perform(post(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI) + .contentType(MediaType.APPLICATION_JSON).content(CREATE_JSON_CONTENT)).andReturn(); + + // Our stub document store DAO returns the parameters that it was + // passed as the result string, so now we can validate that our + // endpoint invoked it with the correct parameters. + + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); + + assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); + } + + /** + * This test validates the behaviour of the 'Create Document' PUT request endpoint. + * + * @throws IOException + * @throws ParseException + */ + @Test + public void updateDocumentTest() throws Exception { + // WebTarget target = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID); + // Builder request = target.request().header("If-Match", "1"); + // String result = request.put(Entity.json(CREATE_JSON_CONTENT), String.class); + + MvcResult result = this.mockMvc + .perform(put(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) + .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) + .andReturn(); + + // Our stub document store DAO returns the parameters that it was + // passed as the result string, so now we can validate that our + // endpoint invoked it with the correct parameters. + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); + + assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); + } + + /** + * This test validates the behaviour of the 'Get Document' GET request endpoint. + * + * @throws IOException + * @throws ParseException + */ + @Test + public void getDocumentTest() throws Exception { + // String result = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID).request().get(String.class); + + // MvcResult result = this.mockMvc.perform ( get ( INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID ) + // ).andReturn (); + MvcResult result = this.mockMvc + .perform(get(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) + .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) + .andReturn(); + + + // Our stub document store DAO returns the parameters that it was + // passed as the result string, so now we can validate that our + // endpoint invoked it with the correct parameters. + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); + + assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); + + } + + // + // /** + // * This test validates the behaviour of the 'Delete Document' DELETE request + // * endpoint. + // * + // * @throws IOException + // * @throws ParseException + // */ + @Test + public void deleteDocumentTest() throws Exception { + // WebTarget target = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID); + // Builder request = target.request().header("If-Match", "1"); + // String result = request.delete(String.class); + MvcResult result = this.mockMvc + .perform(delete(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) + .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) + .andReturn(); + + + + // Our stub document store DAO returns the parameters that it was + // passed as the result string, so now we can validate that our + // endpoint invoked it with the correct parameters. + assertTrue("Unexpected Result ", result.getResponse().getContentAsString().isEmpty()); + + } + + + /** + * This test validates the behaviour of the 'Search Documents' GET request endpoint. + * + * @throws Exception + */ + @Ignore + public void searchDocumentTest1() throws Exception { + MvcResult result = this.mockMvc + .perform(get(INDEXES_URI + INDEX_NAME + "/" + SEARCH_URI + SIMPLE_QUERY) + .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) + .andReturn(); + + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); + + assertTrue("Unexpected Result ", json.get("totalHits").toString().equals("1")); + } + + /** + * This test validates the behaviour of the 'Search Documents' GET request endpoint. + * + * @throws IOException + * @throws ParseException + */ + @Test + public void searchDocumentTest2() throws Exception { + MvcResult result = this.mockMvc.perform(get(INDEXES_URI + INDEX_NAME + "/" + SEARCH_URI) + .contentType(MediaType.APPLICATION_JSON).content(COMPLEX_QUERY)).andReturn(); + + JSONParser parser = new JSONParser(); + JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); + JSONObject resultJson = (JSONObject) json.get("searchResult"); + + assertTrue("Unexpected Result ", resultJson.get("totalHits").toString().equals("1")); + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java new file mode 100644 index 0000000..c2d5021 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java @@ -0,0 +1,99 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import org.junit.Test; + +public class DocumentSchemaTest { + + private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/simpleDocument.json"; + private final String NESTED_DOC_SCHEMA_JSON = "src/test/resources/json/nested-document.json"; + + + /** + * This test validates that we convert document definitions back and forth between json strings and POJOs without + * any loss of data. + * + * @throws com.fasterxml.jackson.core.JsonParseException + * @throws com.fasterxml.jackson.databind.JsonMappingException + * @throws IOException + */ + @Test + public void simpleDocSchemaFromJsonFileTest() throws com.fasterxml.jackson.core.JsonParseException, + com.fasterxml.jackson.databind.JsonMappingException, IOException { + + // Import our json format document schema from a file. + File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); + String fileString = TestUtils.readFileToString(schemaFile); + + // Unmarshall that to a Java POJO + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema docSchema = mapper.readValue(schemaFile, DocumentSchema.class); + + // Now, for the purposes of comparison, produce a JSON string from + // our Java object. + String jsonString = mapper.writeValueAsString(docSchema); + + // Assert that the raw JSON that we read from the file matches the marshalled + // JSON we generated from our Java object (ie: validate that we didn't lose + // anything going in either direction). + assertTrue("Marshalled object does not match the original json source that produced it", + fileString.equals(jsonString)); + } + + // + // /** + // * This test validates that we convert document definitions back and + // * forth between json strings and POJOs without any loss of data in + // * the case of document schemas which contain nested fields. + // * + // * @throws com.fasterxml.jackson.core.JsonParseException + // * @throws com.fasterxml.jackson.databind.JsonMappingException + // * @throws IOException + // */ + + @Test + public void nestedDocSchemaFromJsonFileTest() throws JsonParseException, JsonMappingException, IOException { + + // Import our json format document schema from a file. + File schemaFile = new File(NESTED_DOC_SCHEMA_JSON); + String fileString = TestUtils.readFileToString(schemaFile); + + // Unmarshall that to a Java POJO + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema docSchema = mapper.readValue(schemaFile, DocumentSchema.class); + + String jsonString = mapper.writeValueAsString(docSchema); + + // Assert that the raw JSON that we read from the file matches the marshalled + // JSON we generated from our Java object (ie: validate that we didn't lose + // anything going in either direction). + assertTrue("Marshalled object does not match the original json source that produced it", + fileString.equals(jsonString)); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentTest.java new file mode 100644 index 0000000..e4cf335 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/DocumentTest.java @@ -0,0 +1,727 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import com.fasterxml.jackson.core.JsonProcessingException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +// import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntity; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.ErrorResult; +import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; +import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import java.util.Properties; + + +public class DocumentTest { + + @Mock + SearchServiceApi searchServiceApi; + + @Mock + HttpServletRequest request; + + @Mock + HttpHeaders headers; + + @Mock + HttpServletResponse httpResponse; + + @Mock + DocumentStoreInterface documentStore; + + @Mock + MultivaluedMap multivaluedMap; + + @InjectMocks + IndexApi indexApi; + + DocumentApi documentApi; + + @Mock + ElasticSearchHttpController httpController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + documentApi = new DocumentApi(searchServiceApi); + } + + @Test + public void testDocumentClass_AllMethods() throws JsonProcessingException { + Document doc = new Document(); + doc.setField("name-1", "value-1"); + Assert.assertTrue(doc.getFields().size() == 1); + Assert.assertTrue(doc.toJson().contains("value-1")); + Assert.assertNotNull(doc.toString()); + Assert.assertTrue(doc.toString().contains("name-1")); + } + + @Test + public void testProcessPost_NullContent() { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = null; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + ResponseEntity response = + documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessPost_NotNullContent() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + // + @Test + public void testProcessPost_ValidRequest() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + DocumentOperationResult result = new DocumentOperationResult(); + result.setResultCode(150); + result.setError(new ErrorResult("type-1", "reason-1")); + result.setFailureCause("test-failure"); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), + Mockito.anyBoolean())).thenReturn(result); + Mockito.doNothing().when(httpResponse).setHeader(Mockito.anyString(), Mockito.anyString()); + ResponseEntity response = + documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); + } + + // + @Test + public void testProcessSearchWithGet_Created() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + SearchOperationResult result = new SearchOperationResult(); + result.setResultCode(201); + SearchHits hits = new SearchHits(); + hits.setTotalHits("2"); + result.setSearchResult(hits); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); + ResponseEntity response = + documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.CREATED.value() == response.getStatusCodeValue()); + + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessSearchWithGet_ValidateThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + SearchOperationResult result = new SearchOperationResult(); + result.setResultCode(201); + SearchHits hits = new SearchHits(); + hits.setTotalHits("2"); + result.setSearchResult(hits); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); + ResponseEntity response = + documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + + } + + @Test + public void testProcessSearchWithGet_ValidateIsFalse() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + SearchOperationResult result = new SearchOperationResult(); + result.setResultCode(201); + SearchHits hits = new SearchHits(); + hits.setTotalHits("2"); + result.setSearchResult(hits); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); + ResponseEntity response = + documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + + } + + @Test + public void testProcessSearchWithGet_InvalidResult() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + SearchOperationResult result = new SearchOperationResult(); + result.setResultCode(302); + SearchHits hits = new SearchHits(); + hits.setTotalHits("2"); + result.setSearchResult(hits); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); + ResponseEntity response = + documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); + + } + + @Test + public void testProcessPut_NullContent() { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = null; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + ResponseEntity response = + documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessPut_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessPut_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = + documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessPut_ResultInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + DocumentOperationResult result = new DocumentOperationResult(); + result.setResultCode(302); + result.setError(new ErrorResult("type-1", "reason-1")); + result.setFailureCause("test-failure"); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), + Mockito.anyBoolean())).thenReturn(result); + ResponseEntity response = + documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessDelete_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessDelete_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = + documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Ignore + @Test + public void testProcessDelete_ResultInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + DocumentOperationResult result = new DocumentOperationResult(); + result.setResultCode(302); + result.setError(new ErrorResult("type-1", "reason-1")); + result.setFailureCause("test-failure"); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.deleteDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class))) + .thenReturn(result); + ResponseEntity response = + documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessGet_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessGet_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = + documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessGet_ResultInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + DocumentOperationResult result = new DocumentOperationResult(); + result.setResultCode(302); + result.setError(new ErrorResult("type-1", "reason-1")); + result.setFailureCause("test-failure"); + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.getDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class))) + .thenReturn(result); + ResponseEntity response = + documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); + } + + @Test + public void testQueryWithGetWithPayload_NullContent() { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = null; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + ResponseEntity response = + documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testQueryWithGetWithPayload_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testQueryWithGetWithPayload_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = + documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testCreateProcessIndex_IndexApi_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = + indexApi.processCreateIndex("document-1", request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testCreateProcessIndex_IndexApi_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = + indexApi.processCreateIndex("document-1", request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @Test + public void testCreateProcessIndex_IndexApi_NullDocument() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String documentSchema = null; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + ResponseEntity response = + indexApi.processCreateIndex(documentSchema, request, headers, "index-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); + } + + @Test + public void testProcessDelete_IndexApi_RequestInvalid() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(false); + ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessDelete_IndexApi_RequestThrowsException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenThrow(IllegalArgumentException.class); + ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void testProcessDelete_IndexApi_DeleteIndexException() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenReturn(true); + Mockito.when(documentStore.deleteIndex(Mockito.anyString())).thenThrow(DocumentStoreOperationException.class); + ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); + } + + @Test + public void testUserAuthorization() throws Exception { + String transactionId = "transactionId-1"; + String remoteAddr = "http://127.0.0.1"; + String content = "content"; + // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; + Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); + Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); + Mockito.when(request.getMethod()).thenReturn("testMethod"); + Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); + Mockito.when(request.getRemoteHost()).thenReturn("localhost"); + Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), + Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) + .thenCallRealMethod(); + + Mockito.doAnswer(new Answer() { + public ElasticSearchConfig answer(InvocationOnMock invocation) { + Properties properties = new Properties(); + return new ElasticSearchConfig(properties); + } + }).when(httpController).getElasticSearchConfig(); + + searchServiceApi.documentStore = httpController; + + ResponseEntity response = + documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + + Mockito.doAnswer(new Answer() { + public ElasticSearchConfig answer(InvocationOnMock invocation) { + Properties properties = new Properties(); + properties.put(ElasticSearchConfig.ES_AUTH_ENABLED, "true"); + return new ElasticSearchConfig(properties); + } + }).when(httpController).getElasticSearchConfig(); + + + response = documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); + + Mockito.doAnswer(new Answer() { + public ElasticSearchConfig answer(InvocationOnMock invocation) { + Properties properties = new Properties(); + properties.put(ElasticSearchConfig.ES_AUTH_ENABLED, "false"); + return new ElasticSearchConfig(properties); + } + }).when(httpController).getElasticSearchConfig(); + + DocumentOperationResult result = new DocumentOperationResult(); + result.setResultCode(302); + result.setError(new ErrorResult("type-1", "reason-1")); + result.setFailureCause("test-failure"); + Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), + Mockito.anyBoolean())).thenReturn(result); + response = documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); + Assert.assertNotNull(response); + Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); + + } +} \ No newline at end of file diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java new file mode 100644 index 0000000..ed84a7a --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java @@ -0,0 +1,280 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.junit.Before; +// import org.glassfish.jersey.server.ResourceConfig; +// import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +//import javax.ws.rs.core.Application; +//import javax.ws.rs.core.Response; + + +/** + * This suite of tests is intended to exercise the set of REST endpoints associated with manipulating Indexes in the + * document store. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class IndexApiTest { + + private final String TOP_URI = "/test/indexes/"; + private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/simpleDocument.json"; + private final String DYNAMIC_INDEX_PAYLOAD = "src/test/resources/json/dynamicIndex.json"; + + @Autowired + private MockMvc mockMvc; + + // + // @Override + // protected Application configure() { + // + // // Make sure that our test endpoint is on the resource path + // // for Jersey Test. + // return new ResourceConfig(SearchServiceApiHarness.class); + // } + // + // + + @Before + public void setup() throws Exception { + System.setProperty("CONFIG_HOME", System.getProperty("user.dir") + File.separator + "src/test/resources/json"); + } + + /** + * Tests the dynamic shcema creation flow that send the request JSON to the data store without any JSON validation + * against a schema + * + * @throws IOException + */ + @Test + public void createDynamicIndexTest() throws Exception { + String indexName = "super-ultra-dynamic-mega-index"; + String dynamicUri = TOP_URI + "dynamic/"; + File indexFile = new File(DYNAMIC_INDEX_PAYLOAD); + String indexPayload = TestUtils.readFileToString(indexFile); + + // String result = target(dynamicUri + indexName).request().put(Entity.json(indexPayload), String.class); + MvcResult result = this.mockMvc + .perform(put(dynamicUri + indexName).contentType(MediaType.APPLICATION_JSON).content(indexPayload)) + .andReturn(); + + assertEquals(indexPayload, result.getResponse().getContentAsString()); + } + + + /** + * This test validates that the {@link IndexApi} is able to convert {@link OperationResult} obects to standard REST + * {@link ResponseEntity} objects. + * + * @throws FileNotFoundException + * @throws IOException + * @throws DocumentStoreOperationException + */ + @Test + public void responseFromOperationResultTest() + throws FileNotFoundException, IOException, DocumentStoreOperationException { + + int SUCCESS_RESULT_CODE = 200; + String SUCCESS_RESULT_STRING = "Everything is ay-okay!"; + int FAILURE_RESULT_CODE = 500; + String FAILURE_CAUSE_STRING = "Something went wrong!"; + + + // Create an instance of the index API endpoint that we will test against. + // We will override the init() method because we don't want it to try to + // connect to a real document store. + IndexApi indexApi = new IndexApi(new SearchServiceApiHarness()) { + @Override + public void init() { /* do nothing */ } + }; + // + // Construct an OperationResult instance with a success code and string. + OperationResult successResult = new OperationResult(); + successResult.setResultCode(SUCCESS_RESULT_CODE); + successResult.setResult(SUCCESS_RESULT_STRING); + + // Convert our success OperationResult to a standard REST Response... + ResponseEntity successResponse = indexApi.responseFromOperationResult(successResult); + + // ...and validate that the Response is correctly populated. + assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, successResponse.getStatusCodeValue()); + assertTrue("Incorrect result string", ((String) successResponse.getBody()).equals(SUCCESS_RESULT_STRING)); + + // Construct an OperationResult instance with an error code and failure + // cause. + OperationResult failureResult = new OperationResult(); + failureResult.setResultCode(FAILURE_RESULT_CODE); + failureResult.setFailureCause(FAILURE_CAUSE_STRING); + + // Convert our failure OperationResult to a standard REST Response... + ResponseEntity failureResponse = indexApi.responseFromOperationResult(failureResult); + + // ...and validate that the Response is correctly populated. + assertEquals("Unexpected result code", FAILURE_RESULT_CODE, failureResponse.getStatusCodeValue()); + assertTrue("Incorrect result string", ((String) failureResponse.getBody()).equals(FAILURE_CAUSE_STRING)); + } + + // + // + // /** + // * This test validates the behaviour of the 'Create Index' POST request + // * endpoint. + // * + // * @throws IOException + // */ + @Test + public void createIndexTest() throws Exception { + + String INDEX_NAME = "test-index"; + String EXPECTED_SETTINGS = "{\"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\"]}}}}"; + String EXPECTED_MAPPINGS = + "{\"dynamic_templates\":[{\"strings\":{\"match_mapping_type\":\"string\",\"match\":\"*\",\"mapping\":{\"type\":\"text\",\"fielddata\":true}}}]" + + ",\"properties\": {" + "\"serverName\": {" + "\"type\": \"string\", " + + "\"index\": \"analyzed\", " + "\"search_analyzer\": \"whitespace\"}, " + + "\"serverComplex\": {" + "\"type\": \"string\", " + "\"search_analyzer\": \"whitespace\"}}}"; + + // Read a valid document schema from a json file. + File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); + String documentJson = TestUtils.readFileToString(schemaFile); + + // Send a request to our 'create index' endpoint, using the schema + // which we just read. + // String result = target(TOP_URI + INDEX_NAME).request().put(Entity.json(documentJson), String.class); + MvcResult result = this.mockMvc + .perform(put(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON).content(documentJson)) + .andReturn(); + + + // Our stub document store DAO returns the parameters that it was + // passed as the result string, so now we can validate that our + // endpoint invoked it with the correct parameters. + String[] tokenizedResult = result.getResponse().getContentAsString().split("@"); + assertTrue("Unexpected Index Name '" + tokenizedResult[0] + "' passed to doc store DAO", + tokenizedResult[0].equals(INDEX_NAME)); + assertTrue("Unexpected settings string '" + tokenizedResult[1] + "' passed to doc store DAO", + tokenizedResult[1].equals(EXPECTED_SETTINGS)); + assertTrue("Unexpected mappings string '" + tokenizedResult[2] + "' passed to doc store DAO", + tokenizedResult[2].equals(EXPECTED_MAPPINGS)); + } + + // + // + /** + * This test validates that a 'create index' request with an improperly formatted document schema as the payload + * will result in an appropriate error being returned from the endpoint. + */ + @Test + public void createIndexWithMangledSchemaTest() throws Exception { + + String INDEX_NAME = "test-index"; + int BAD_REQUEST_CODE = 400; + + String invalidSchemaString = "this is definitely not json!"; + + // ResponseEntity result = target(TOP_URI + INDEX_NAME).request().put(Entity.json(invalidSchemaString), + // ResponseEntity.class); + MvcResult result = this.mockMvc + .perform(put(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON).content(invalidSchemaString)) + .andReturn(); + + assertEquals("Invalid document schema should result in a 400 error", BAD_REQUEST_CODE, + result.getResponse().getStatus()); + } + + // + // + /** + * This test validates the behaviour of the 'Delete Index' end point. + */ + @Test + public void deleteIndexTest() throws Exception { + + String INDEX_NAME = "test-index"; + + // Send a request to the 'delete index' endpoint. + // String result = target(TOP_URI + INDEX_NAME).request().delete(String.class); + + MvcResult result = this.mockMvc.perform(delete(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON) + .header("If-Match", "1").content("Some Json")).andReturn(); + + // Validate that the expected parameters were passed to the document + // store DAO. + assertTrue("Unexpected index name '" + result.getResponse().getContentAsString() + "' passed to doc store DAO", + result.getResponse().getContentAsString().equals(INDEX_NAME)); + } + + // + // + // /** + // * This test validates that attempting to delete an index which does not + // * exist results in a 404 error. + // */ + @Test + public void deleteIndexDoesNotExistTest() throws Exception { + + int NOT_FOUND_CODE = 404; + + // Send a request to the 'delete index' endpoint, specifying a + // non-existent index. + // ResponseEntity result = target(TOP_URI + + // StubEsController.DOES_NOT_EXIST_INDEX).request().delete(ResponseEntity.class); + + MvcResult result = + this.mockMvc + .perform(delete(TOP_URI + StubEsController.DOES_NOT_EXIST_INDEX) + .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content("Some Json")) + .andReturn(); + + + // Validate that a 404 error code is returned from the end point. + assertEquals("Deleting an index which does not exist should result in a 404 error", NOT_FOUND_CODE, + result.getResponse().getStatus()); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java new file mode 100644 index 0000000..93e1d49 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java @@ -0,0 +1,164 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@Component +@RestController +@RequestMapping("/test") +public class SearchServiceApiHarness extends SearchServiceApi { + + + public static final String FAIL_AUTHENTICATION_TRIGGER = "FAIL AUTHENTICATION"; + + private boolean authenticationShouldSucceed = true; + + + /** + * Performs all one-time initialization required for the end point. + */ + @Override + public void init() { + + // Instantiate our Document Store DAO. + documentStore = new StubEsController(); + } + + @Override + @RequestMapping(value = "/indexes/dynamic/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) + public ResponseEntity processCreateDynamicIndex(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + return super.processCreateDynamicIndex(requestBody, request, headers, index); + } + + + @Override + @RequestMapping(value = "/indexes/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) + public ResponseEntity processCreateIndex(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + return super.processCreateIndex(requestBody, request, headers, index); + } + + @Override + @RequestMapping(value = "/indexes/{index}", method = RequestMethod.DELETE, consumes = {"application/json"}) + public ResponseEntity processDeleteIndex(HttpServletRequest request, @RequestHeader HttpHeaders headers, + @PathVariable("index") String index) { + + return super.processDeleteIndex(request, headers, index); + } + + @Override + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.GET) + public ResponseEntity processGetDocument(HttpServletRequest request, HttpServletResponse httpResponse, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { + + return super.processGetDocument(request, httpResponse, headers, index, id); + } + + @Override + @RequestMapping(value = "/indexes/{index}/documents", method = RequestMethod.POST, + consumes = {"application/json", "application/xml"}) + public ResponseEntity processCreateDocWithoutId(@RequestBody String requestBody, HttpServletRequest request, + HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + return super.processCreateDocWithoutId(requestBody, request, httpResponse, headers, index); + } + + @Override + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.PUT, + consumes = {"application/json", "application/xml"}) + public ResponseEntity processUpsertDoc(@RequestBody String requestBody, HttpServletRequest request, + HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index, + @PathVariable("id") String id) { + + return super.processUpsertDoc(requestBody, request, httpResponse, headers, index, id); + } + + @Override + @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.DELETE, + consumes = {"application/json"}) + public ResponseEntity processDeleteDoc(HttpServletRequest request, HttpServletResponse httpResponse, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { + + return super.processDeleteDoc(request, httpResponse, headers, index, id); + } + + @Override + @RequestMapping(value = "/indexes/{index}/query/{queryText}", method = RequestMethod.GET) + public ResponseEntity processInlineQuery(HttpServletRequest request, @RequestHeader HttpHeaders headers, + @PathVariable("index") String index, @PathVariable("queryText") String queryText) { + + return super.processInlineQuery(request, headers, index, queryText); + } + + @Override + @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.GET, consumes = {"application/json"}) + public ResponseEntity processQueryWithGet(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + return super.processQueryWithGet(requestBody, request, headers, index); + } + + @Override + @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.POST, consumes = {"application/json"}) + public ResponseEntity processQuery(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { + + return super.processQuery(requestBody, request, headers, index); + } + + @Override + @RequestMapping(value = "/bulk", method = RequestMethod.POST, consumes = {"application/json"}, + produces = {"application/json"}) + public ResponseEntity processBulkRequest(@RequestBody String requestBody, HttpServletRequest request, + @RequestHeader HttpHeaders headers) { + + // If the operations string contains a special keyword, set the + // harness to fail the authentication validation. + if (requestBody.contains(FAIL_AUTHENTICATION_TRIGGER)) { + authenticationShouldSucceed = false; + } + + // Just pass the request up to the parent, since that is the code + // that we really want to test. + // return super.processPost(operations, request, headers, index); + return super.processBulkRequest(requestBody, request, headers); + } + + @Override + protected boolean validateRequest(HttpHeaders headers, HttpServletRequest req, ApiUtils.Action action, + String authPolicyFunctionName) { + return authenticationShouldSucceed; + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java new file mode 100644 index 0000000..9cc4e3b --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 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========================================================= + */ +package org.onap.aai.sa.rest; + +import org.junit.Assert; +import org.junit.Test; + + +public class SettingConfigurationTest { + + @Test + public void settingConfigTest() throws Exception { + SettingConfiguration config = new SettingConfiguration(); + config.init("src/test/resources/json/settings-config.json"); + String settings = config.getSettings(); + System.out.println("SettingsConfig:\n" + settings); + Assert.assertTrue(settings.contains("number_of_shards")); + } + + @Test + public void settingConfigAnalysisTest() throws Exception { + AnalysisConfiguration ac = new AnalysisConfiguration(); + ac.init("src/test/resources/json/filter-config.json", "src/test/resources/json/analysis-config.json"); + System.out.println("AnalysisConfig:\n" + ac.buildEsIndexSettings()); + + SettingConfiguration config = new SettingConfiguration(); + config.init("src/test/resources/json/settings-config.json"); + String settings = config.getSettingsWithAnalysis(ac); + System.out.println("SettingsAnalysisConfig:\n" + settings); + Assert.assertTrue(settings.contains("number_of_shards")); + Assert.assertTrue(settings.contains("nGram_analyzer")); + + config = new SettingConfiguration(); + config.init("src/test/resources/json/missing-file.json"); + settings = config.getSettingsWithAnalysis(ac); + System.out.println("SettingsAnalysisConfigMissing:\n" + settings); + Assert.assertFalse(ac.getEsIndexSettings().isEmpty()); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/StubEsController.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/StubEsController.java new file mode 100644 index 0000000..cb4edbc --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/StubEsController.java @@ -0,0 +1,266 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.rest; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.json.simple.JSONObject; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntity; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.entity.Document; +import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; +import org.onap.aai.sa.searchdbabstraction.entity.SearchHit; +import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; +import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; +import org.onap.aai.sa.searchdbabstraction.util.DocumentSchemaUtil; + +/** + * This class implements a stubbed version of the document store DAO so that we can run unit tests without trying to + * connect to a real document store. + */ +public class StubEsController implements DocumentStoreInterface { + + public static final String DOES_NOT_EXIST_INDEX = "index-does-not-exist"; + + private AnalysisConfiguration analysisConfig = null; + + /** + * + */ + // private IndexAPIHarness indexAPIHarness; + + StubEsController() { + analysisConfig = new AnalysisConfiguration(); + analysisConfig.init("src/test/resources/json/filter-config.json", + "src/test/resources/json/analysis-config.json"); + } + + + @Override + public OperationResult createIndex(String index, DocumentSchema documentSchema) { + + // Just return an OK result, with the parameters that we were passed + // bundled in the response string. This allows unit tests to validate + // that those parameters match what they expected to be passed. + OperationResult opResult = new OperationResult(); + opResult.setResultCode(200); + + try { + opResult.setResult(index + "@" + analysisConfig.getEsIndexSettings() + "@" + + DocumentSchemaUtil.generateDocumentMappings(documentSchema)); + } catch (IOException e) { + e.printStackTrace(); + } + + return opResult; + } + + @Override + public OperationResult createDynamicIndex(String index, String dynamicSchema) { + OperationResult opResult = new OperationResult(); + opResult.setResultCode(200); + // Directly return the json as this flow should not edit the json in any way + opResult.setResult(dynamicSchema); + return opResult; + } + + + @Override + public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { + + OperationResult opResult = new OperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + opResult.setResult(indexName); + } + + return opResult; + } + + @Override + public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { + + DocumentOperationResult opResult = buildSampleDocumentOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + opResult.setResultVersion("1"); + } + + return opResult; + } + + @Override + public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, + boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { + + DocumentOperationResult opResult = buildSampleDocumentOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + String version = "1"; + if (document.getVersion() != null) { + version = String.valueOf(Integer.parseInt(document.getVersion()) + 1); + } + opResult.setResultVersion(version); + } + + return opResult; + } + + @Override + public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + DocumentOperationResult opResult = buildSampleDocumentOperationResult(); + + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + if (opResult.getDocument() != null) { + opResult.getDocument().setEtag(null); + opResult.getDocument().setUrl(null); + opResult.setResultVersion("1"); + } + opResult.setResultCode(200); + opResult.setResult(indexName + "@" + document.getId()); + opResult.setResultVersion("1"); + } + + return opResult; + } + + @Override + public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) + throws DocumentStoreOperationException { + DocumentOperationResult opResult = buildSampleDocumentOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + // Adding it to make the tests pass. + opResult.setResultVersion("1"); + } else { + opResult.setResultCode(200); + // Adding it to make the tests pass. + opResult.setResultVersion("1"); + } + + return opResult; + } + + @Override + public SearchOperationResult search(String indexName, String queryText) throws DocumentStoreOperationException { + + SearchOperationResult opResult = buildSampleSearchOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + opResult.setResult(indexName + "@" + queryText); + } + + return opResult; + } + + @Override + public SearchOperationResult searchWithPayload(String indexName, String query) + throws DocumentStoreOperationException { + SearchOperationResult opResult = buildSampleSearchOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + opResult.setResult(indexName + "@" + query); + } + + return opResult; + } + + @Override + public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) + throws DocumentStoreOperationException { + SearchOperationResult opResult = new SearchOperationResult(); + + if (indexName.equals(DOES_NOT_EXIST_INDEX)) { + opResult.setResultCode(404); + } else { + opResult.setResultCode(200); + opResult.setResult(indexName + "@" + query); + } + + return opResult; + } + + @Override + public OperationResult performBulkOperations(BulkRequest[] requests) throws DocumentStoreOperationException { + + OperationResult opResult = new OperationResult(); + opResult.setResultCode(200); + + return opResult; + } + + private DocumentOperationResult buildSampleDocumentOperationResult() { + DocumentOperationResult result = new DocumentOperationResult(); + Document doc = new Document(); + doc.setEtag("etag1"); + + doc.setContent(new JSONObject()); + result.setDocument(doc); + return result; + } + + private SearchOperationResult buildSampleSearchOperationResult() { + SearchOperationResult result = new SearchOperationResult(); + + SearchHits searchHits = new SearchHits(); + SearchHit[] searchHitArray = new SearchHit[1]; + SearchHit searchHit = new SearchHit(); + Document doc = new Document(); + doc.setEtag("etag1"); + Map content = new HashMap<>(); + content.put("key1", "value1"); + doc.setContent(new JSONObject()); + searchHit.setDocument(doc); + searchHitArray[0] = searchHit; + + searchHits.setHits(searchHitArray); + searchHits.setTotalHits("1"); + result.setSearchResult(searchHits); + + return result; + + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/rest/TestUtils.java b/search-data-service/src/test/java/org/onap/aai/sa/rest/TestUtils.java new file mode 100644 index 0000000..0d2c615 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/rest/TestUtils.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ + +package org.onap.aai.sa.rest; + +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +public class TestUtils { + + /** + * This helper method reads the contents of a file into a simple string. + * + * @param aFile - The file to be imported. + * + * @return - The file contents expressed as a simple string. + * + * @throws IOException + */ + public static String readFileToString(File aFile) throws IOException { + + BufferedReader br = new BufferedReader(new FileReader(aFile)); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + line = br.readLine(); + } + + return sb.toString().replaceAll("\\s+", ""); + } finally { + try { + br.close(); + } catch (IOException e) { + fail("Unexpected IOException: " + e.getMessage()); + } + } + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java new file mode 100644 index 0000000..e840e2c --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.config; + +import java.util.Properties; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class ElasticSearchConfigTest { + + @Autowired + ElasticSearchConfig elasticSearchConfig; + + @Before + public void setUp() { + Properties prop = new Properties(); + prop.put("es.cluster-name", "cluster-1"); + prop.put("es.ip-address", "127.0.0.1"); + prop.put("es.http-port", "9001"); + // elasticSearchConfig = new ElasticSearchConfig(prop); + } + + @Ignore + @Test + public void testAllGetMethods() { + Assert.assertEquals(elasticSearchConfig.getClusterName(), "cluster-1"); + Assert.assertEquals(elasticSearchConfig.getIpAddress(), "127.0.0.1"); + Assert.assertEquals(elasticSearchConfig.getHttpPort(), "9001"); + Assert.assertEquals(elasticSearchConfig.getJavaApiPort(), "9300"); + Assert.assertNotNull(elasticSearchConfig.toString()); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java new file mode 100644 index 0000000..fbc077d --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java @@ -0,0 +1,99 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.junit.Test; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; +import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; +import org.onap.aai.sa.searchdbabstraction.util.AggregationParsingUtil; + +public class AggregationResponseParsingTest { + + @Test + public void testParseAggregationResponse() { + JSONParser parser = new JSONParser(); + JSONObject root; + + String input = + "{\r\n \"aggregations\": {\r\n \"violations\": {\r\n \"doc_count\": 2,\r\n \"by_Timestamp\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": 7199992,\r\n \"key_as_string\": \"Jan 1 1970 01:59:59\",\r\n \"doc_count\": 2\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n}"; + + try { + root = (JSONObject) parser.parse(input); + JSONObject aggregations = (JSONObject) root.get("aggregations"); + AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); + AggregationResults aggs = new AggregationResults(); + ObjectMapper mapper = new ObjectMapper(); + aggs.setAggregations(results); + System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() + .writeValueAsString(aggs)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testParseAggregationResponse2() { + JSONParser parser = new JSONParser(); + JSONObject root; + + String input = + "{\r\n \"aggregations\": {\r\n \"entityType\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": \"entity1\",\r\n \"doc_count\": 5,\r\n \"byVersion\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": \"0\",\r\n \"doc_count\": 5\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n}"; + + try { + root = (JSONObject) parser.parse(input); + JSONObject aggregations = (JSONObject) root.get("aggregations"); + AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); + AggregationResults aggs = new AggregationResults(); + ObjectMapper mapper = new ObjectMapper(); + aggs.setAggregations(results); + System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() + .writeValueAsString(aggs)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testParseAggregationResponse3() { + JSONParser parser = new JSONParser(); + JSONObject root; + + String input = + "{\r\n \"aggregations\": {\r\n \"validateTimes\": {\r\n \"buckets\": [\r\n {\r\n \"key\": \"Jan 10 2017 21:6:6-Jan 24 2017 13:43:5\",\r\n \"from\": 1484082366000,\r\n \"from_as_string\": \"Jan 10 2017 21:6:6\",\r\n \"to\": 1485265385000,\r\n \"to_as_string\": \"Jan 24 2017 13:43:5\",\r\n \"doc_count\": 95\r\n },\r\n {\r\n \"key\": \"Feb 3 2017 18:27:39-*\",\r\n \"from\": 1486146459000,\r\n \"from_as_string\": \"Feb 3 2017 18:27:39\",\r\n \"doc_count\": 2\r\n }\r\n ]\r\n }\r\n }\r\n}"; + + try { + root = (JSONObject) parser.parse(input); + JSONObject aggregations = (JSONObject) root.get("aggregations"); + AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); + AggregationResults aggs = new AggregationResults(); + ObjectMapper mapper = new ObjectMapper(); + aggs.setAggregations(results); + System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() + .writeValueAsString(aggs)); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java new file mode 100644 index 0000000..007e3fc --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java @@ -0,0 +1,330 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.either; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; + +import java.util.Properties; +import org.eclipse.jetty.util.security.Password; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.aai.sa.rest.AnalysisConfiguration; +import org.onap.aai.sa.rest.DocumentSchema; +import org.onap.aai.sa.rest.SettingConfiguration; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; +import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; + +@Ignore("All tests in this classes require an Elasticsearch instance to run locally") +public class ElasticSearchHttpControllerTest { + + static { + // Set the location of the payload translation JSON file. + System.setProperty("CONFIG_HOME", "src/test/resources/json"); + } + + private static ElasticSearchHttpController elasticSearch; + private static AAIEntityTestObject testDocument; + + private static final String TEST_INDEX_NAME = "test"; + + private static final String indexMappings = + "{\r\n \"properties\": {\r\n \"entityType\": {\r\n \"type\": \"text\"\r\n },\r\n" + + " \"edgeTagQueryEntityFieldName\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n" + + " \"edgeTagQueryEntityFieldValue\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n \"searchTagIDs\" : {\r\n \"type\" : \"text\"\r\n },\r\n \"searchTags\": {\r\n \"type\": \"text\",\r\n \"analyzer\": \"nGram_analyzer\",\r\n \"search_analyzer\": \"whitespace_analyzer\"\r\n }\r\n }\r\n}"; + private static final String indexSettings = + "{\r\n \"analysis\": {\r\n \"filter\": {\r\n \"nGram_filter\": {\r\n \"type\": \"nGram\",\r\n \"min_gram\": 1,\r\n \"max_gram\": 50,\r\n \"token_chars\": [\r\n \"letter\",\r\n \"digit\",\r\n \"punctuation\",\r\n \"symbol\"\r\n ]\r\n }\r\n },\r\n \"analyzer\": {\r\n \"nGram_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\",\r\n \"nGram_filter\"\r\n ]\r\n },\r\n \"whitespace_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\"\r\n ]\r\n }\r\n }\r\n }\r\n}"; + + @Before + public void setUp() throws Exception { + Properties properties = new Properties(); + properties.put(ElasticSearchConfig.ES_IP_ADDRESS, "127.0.0.1"); + properties.put(ElasticSearchConfig.ES_HTTP_PORT, "9200"); + properties.put(ElasticSearchConfig.ES_URI_SCHEME, "http"); + properties.put(ElasticSearchConfig.ES_AUTH_USER, "your_user_here"); + properties.put(ElasticSearchConfig.ES_AUTH_ENC, Password.obfuscate("your_password_here")); + elasticSearch = new ElasticSearchHttpController(new ElasticSearchConfig(properties)); + + testDocument = new AAIEntityTestObject(); + testDocument.setId("test123"); + testDocument.setEntityType("service-instance"); + testDocument.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + testDocument.setEdgeTagQueryEntityFieldValue("123456"); + testDocument.setSearchTagIDs("0"); + testDocument.setSearchTags("service-instance-id"); + } + + @Test + public void testGetInstance() throws Exception { + ElasticSearchHttpController.getInstance(); + } + + @Test + public void testCreateIndex() throws Exception { + testDeleteIndex(); + OperationResult result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); + assertThat(result.getResult(), containsString("/search/indexes/test")); + assertThat(result.getResultCode(), is(201)); + + result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); + assertThat(result.getResult(), containsString("already exists")); + assertThat(result.getResultCode(), is(400)); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateDynamicIndexEmptySchema() throws Exception { + elasticSearch.createDynamicIndex(TEST_INDEX_NAME, ""); + } + + @Test + public void testCreateDynamicIndex() throws Exception { + String indexName = "test_dynamic"; + elasticSearch.deleteIndex(indexName); + + OperationResult result = elasticSearch.createDynamicIndex(indexName, + "{\"mappings\":{\"_doc\":{\"dynamic_templates\":[{\"strings_as_text\":{\"match_mapping_type\":\"string\",\"mapping\":{\"type\":\"text\"}}}]}}}"); + assertThat(result.getResult(), containsString("/search/indexes/test")); + assertThat(result.getResultCode(), is(201)); + + elasticSearch.deleteIndex(indexName); + } + + @Test + public void testCreateTable() throws Exception { + AnalysisConfiguration ac = new AnalysisConfiguration(); + ac.init("src/test/resources/json/filter-config.json", "src/test/resources/json/analysis-config.json"); + SettingConfiguration sc = new SettingConfiguration(); + sc.init("src/test/resources/json/settings-config.json"); + + OperationResult result = + elasticSearch.createTable(TEST_INDEX_NAME, "aai-entities", ac, indexMappings, sc); + assertThat(result.getResult(), containsString("\"index\":\"test\"}")); + assertThat(result.getResultCode(), either(is(200)).or(is(400))); + } + + @Test + public void testCreateDocument() throws Exception { + OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, testDocument, false); + assertThat(result.getResult(), not(equalTo(""))); + + DocumentStoreDataEntityImpl ds = new DocumentStoreDataEntityImpl(); + ds.setId(testDocument.getId()); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, ds); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void testCreateDocumentInvalidIndex() throws Exception { + OperationResult result = elasticSearch.createDocument("index_does_not_exist", testDocument, false); + assertThat(result.getResultCode(), is(404)); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void testUpdateDocument() throws Exception { + testDocument.setEdgeTagQueryEntityFieldValue("567890"); + + OperationResult result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + if (result.getResultCode() == 404) { + testCreateDocument(); + } + // assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); + // assertThat(result.getResult(), containsString("\"found\":true")); + + result = elasticSearch.updateDocument(TEST_INDEX_NAME, testDocument, false); + assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString("test123")); + } + + @Test + public void testDeleteDocument() throws Exception { + OperationResult result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + if (result.getResultCode() == 404) { + testCreateDocument(); + } + + result = elasticSearch.deleteDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString(TEST_INDEX_NAME)); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString("test123")); + } + + @Test + public void testBulkCreateDocuments() throws Exception { + for (int i = 0; i < 10; i++) { + AAIEntityTestObject doc = new AAIEntityTestObject(); + doc.setId("test-" + i); + doc.setEntityType("service-instance"); + doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + doc.setEdgeTagQueryEntityFieldValue("123456" + i); + doc.setSearchTagIDs("" + i); + doc.setSearchTags("service-instance-id"); + + OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); + assertThat(result.getResultCode(), anyOf(equalTo(201), equalTo(400))); + } + } + + @Test + public void serchByEntityType() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=instance"); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void serchByTagIDs() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=9"); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void serchByTags() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=service"); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void searchWithPayload() throws Exception { + testCreateIndex(); + OperationResult result = + elasticSearch.searchWithPayload(TEST_INDEX_NAME, "{\"query\":{\"term\":{\"user\":\"fred\"}}}"); + assertThat(result.getResult(), containsString("successful")); + assertThat(result.getResultCode(), is(equalTo(200))); + } + + /** + * The _suggest endpoint appears to be deprecated in ES 5.x and above. + */ + @Test + public void suggestionQueryWithPayload() throws Exception { + testCreateIndex(); + OperationResult result = elasticSearch.suggestionQueryWithPayload(TEST_INDEX_NAME, + "{\"my-suggestion\":{\"text\":\"fred\",\"term\":{\"field\":\"body\"}}}"); + assertThat(result.getResult(), containsString("error")); + assertThat(result.getResultCode(), is(equalTo(400))); + } + + @Test + public void testCreateDocumentWithoutId() throws Exception { + AAIEntityTestObject doc = new AAIEntityTestObject(); + doc.setEntityType("service-instance"); + doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + doc.setEdgeTagQueryEntityFieldValue("1111111"); + doc.setSearchTagIDs("321"); + doc.setSearchTags("service-instance-id"); + + OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); + assertThat(result.getResult(), not(equalTo(""))); + } + + @Test + public void testDeleteIndex() throws Exception { + OperationResult result = elasticSearch.deleteIndex(TEST_INDEX_NAME); + assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(404))); + assertThat(result.getResult(), not(equalTo(""))); + } + + class AAIEntityTestObject implements DocumentStoreDataEntity { + private String id; + private String entityType; + private String edgeTagQueryEntityFieldName; + private String edgeTagQueryEntityFieldValue; + private String searchTagIDs; + private String searchTags; + + public void setId(String id) { + this.id = id; + } + + @Override + public String getId() { + return this.id; + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public String getEdgeTagQueryEntityFieldName() { + return edgeTagQueryEntityFieldName; + } + + public void setEdgeTagQueryEntityFieldName(String edgeTagQueryEntityFieldName) { + this.edgeTagQueryEntityFieldName = edgeTagQueryEntityFieldName; + } + + public String getEdgeTagQueryEntityFieldValue() { + return edgeTagQueryEntityFieldValue; + } + + public void setEdgeTagQueryEntityFieldValue(String edgeTagQueryEntityFieldValue) { + this.edgeTagQueryEntityFieldValue = edgeTagQueryEntityFieldValue; + } + + public String getSearchTagIDs() { + return searchTagIDs; + } + + public void setSearchTagIDs(String searchTagIDs) { + this.searchTagIDs = searchTagIDs; + } + + public String getSearchTags() { + return searchTags; + } + + public void setSearchTags(String searchTags) { + this.searchTags = searchTags; + } + + @Override + public String getVersion() { + return "1"; + } + + @Override + public String getContentInJson() { + return new JSONObject(). // + put("entityType", entityType) // + .put("edgeTagQueryEntityFieldName", edgeTagQueryEntityFieldName) + .put("edgeTagQueryEntityFieldValue", edgeTagQueryEntityFieldValue) // + .put("searchTagIDs", searchTagIDs) // + .put("searchTags", searchTags) // + .toString(); + } + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java new file mode 100644 index 0000000..eef7742 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java @@ -0,0 +1,119 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; + +import org.junit.Assert; +import org.junit.Test; + +public class ElasticSearchResultItemTest { + + @Test + public void testAllMethods() { + ElasticSearchShardStatus shardStatus = new ElasticSearchShardStatus(); + shardStatus.setTotal(10); + shardStatus.setSuccessful(0); + shardStatus.setFailed(1); + Assert.assertEquals(shardStatus.getTotal(), 10); + Assert.assertEquals(shardStatus.getSuccessful(), 0); + Assert.assertEquals(shardStatus.getFailed(), 1); + + ElasticSearchCause cause = new ElasticSearchCause(); + cause.setType("type-1"); + cause.setReason("reason-1"); + Assert.assertEquals(cause.getType(), "type-1"); + Assert.assertEquals(cause.getReason(), "reason-1"); + + ElasticSearchError error = new ElasticSearchError(); + error.setType("type-1"); + error.setReason("reason-1"); + error.setCausedBy(cause); + Assert.assertEquals(error.getType(), "type-1"); + Assert.assertEquals(error.getReason(), "reason-1"); + Assert.assertNotNull(error.getCausedBy()); + error.setAdditionalProperties("name-1", "value-1"); + Assert.assertNotNull(error.getAdditionalProperties()); + + // Create Status + ElasticSearchResultItem resultItem1 = new ElasticSearchResultItem(); + resultItem1.setCreate(getStatus(shardStatus, error)); + Assert.assertNotNull(resultItem1.getCreate()); + Assert.assertEquals(resultItem1.operationType(), "create"); + Assert.assertEquals(resultItem1.operationStatus(), resultItem1.getCreate()); + Assert.assertTrue(resultItem1.toString().contains("create")); + Assert.assertNotNull(resultItem1.toJson()); + + // Index Status + ElasticSearchResultItem resultItem2 = new ElasticSearchResultItem(); + resultItem2.setIndex(getStatus(shardStatus, error)); + Assert.assertNotNull(resultItem2.getIndex()); + Assert.assertEquals(resultItem2.operationType(), "update"); + Assert.assertEquals(resultItem2.operationStatus(), resultItem2.getIndex()); + Assert.assertTrue(resultItem2.toString().contains("index")); + Assert.assertNotNull(resultItem2.toJson()); + + // Delete Status + ElasticSearchResultItem resultItem3 = new ElasticSearchResultItem(); + resultItem3.setDelete(getStatus(shardStatus, error)); + Assert.assertNotNull(resultItem3.getDelete()); + Assert.assertEquals(resultItem3.operationType(), "delete"); + Assert.assertEquals(resultItem3.operationStatus(), resultItem3.getDelete()); + Assert.assertTrue(resultItem3.toString().contains("delete")); + Assert.assertNotNull(resultItem3.toJson()); + + // Unknown Status + ElasticSearchResultItem resultItem4 = new ElasticSearchResultItem(); + Assert.assertEquals(resultItem4.operationType(), "unknown"); + Assert.assertNull(resultItem4.operationStatus()); + + // ElasticSearchBulkOperationResult + ElasticSearchResultItem[] resultItems = {resultItem1, resultItem2, resultItem3}; + ElasticSearchBulkOperationResult result = new ElasticSearchBulkOperationResult(); + result.setErrors(true); + result.setTook(new Integer(10)); + result.setItems(resultItems); + Assert.assertTrue(result.getErrors()); + Assert.assertEquals(result.getTook(), new Integer(10)); + Assert.assertNotNull(result.getItems()); + Assert.assertNotNull(result.toString()); + } + + private ElasticSearchOperationStatus getStatus(ElasticSearchShardStatus shardStatus, ElasticSearchError error) { + ElasticSearchOperationStatus status = new ElasticSearchOperationStatus(); + status.setIndex("index-1"); + status.setType("type-1"); + status.setId("id-1"); + status.setVersion("1.0"); + status.setShards(shardStatus); + status.setStatus(new Integer(1)); + status.setError(error); + status.setAdditionalProperties("REQUEST_URL", "http://127.0.0.1"); + Assert.assertEquals(status.getIndex(), "index-1"); + Assert.assertEquals(status.getType(), "type-1"); + Assert.assertEquals(status.getId(), "id-1"); + Assert.assertEquals(status.getVersion(), "1.0"); + Assert.assertEquals(status.getStatus(), new Integer(1)); + Assert.assertNotNull(status.getShards()); + Assert.assertNotNull(status.getError()); + Assert.assertNotNull(status.getAdditionalProperties()); + return status; + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java new file mode 100644 index 0000000..bff0f4f --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java @@ -0,0 +1,154 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class AggregationStatementTest { + + private static ObjectMapper mapper = new ObjectMapper(); + + @Test + public void testGroupBy() { + String input = "{\r\n \"group-by\": {\r\n \"field\": \"entityType\"\r\n }\r\n }"; + + String expected = "{\"terms\": {\"field\": \"entityType\"}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + @Test + public void testDateRange() { + String input = + "{\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ],\r\n \"format\": \"MM-yyy\",\r\n \"size\": \"5\"\r\n }\r\n}"; + + String expected = + "{\"date_range\": {\"field\": \"mydate\", \"format\": \"MM-yyy\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}], \"size\": 5}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + @Test + public void testDateHistogram() { + String input = + "{\r\n \"date-histogram\": {\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\"\r\n }\r\n}"; + + String expected = "{\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\"}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + @Test + public void testSubAggregation1() { + String input = + "{\r\n \"group-by\": {\r\n \"field\": \"severity\"\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byType\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"entityType\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; + String expected = + "{\"terms\": {\"field\": \"severity\"}, \"aggs\": {\"byType\": {\"terms\": {\"field\": \"entityType\"}}}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + @Test + public void testSubAggregation2() { + String input = + "{\r\n \"group-by\": {\r\n \"field\": \"severity\"\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byType\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violationType\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"byRule\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"validationRule\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; + String expected = + "{\"terms\": {\"field\": \"severity\"}, \"aggs\": {\"byType\": {\"terms\": {\"field\": \"violationType\"}},\"byRule\": {\"terms\": {\"field\": \"validationRule\"}}}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + + @Test + public void testNestedAggregation1() { + String input = + "{\r\n \"nested\": [{\r\n \"name\": \"by_severity\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.severity\"\r\n }\r\n }\r\n }]\r\n}"; + String expected = + "{\"nested\": {\"path\": \"violations\"}, \"aggs\": {\"by_severity\": {\"terms\": {\"field\": \"violations.severity\"}}}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + @Test + public void testNestedAggregation2() { + String input = + "{\r\n \"nested\": [\r\n {\r\n \"name\": \"by_severity\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.severity\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"by_type\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.violationType\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; + String expected = + "{\"nested\": {\"path\": \"violations\"}, \"aggs\": {\"by_severity\": {\"terms\": {\"field\": \"violations.severity\"}},\"by_type\": {\"terms\": {\"field\": \"violations.violationType\"}}}}"; + + AggregationStatement actual; + try { + actual = mapper.readValue(input, AggregationStatement.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java new file mode 100644 index 0000000..12b18d1 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class AggregationTest { + private static ObjectMapper mapper = new ObjectMapper(); + + // + @Test + public void test() { + String input = + "{\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ]\r\n },\r\n \"sub-aggregations\": [{\r\n \"name\": \"byTerm\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"myterm\"\r\n }\r\n }\r\n }]\r\n }\r\n}"; + + String expected = + "\"byDate\": {\"date_range\": {\"field\": \"mydate\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}]}, \"aggs\": {\"byTerm\": {\"terms\": {\"field\": \"myterm\"}}}}"; + + Aggregation actual; + try { + actual = mapper.readValue(input, Aggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java new file mode 100644 index 0000000..005cb76 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class DateHistogramAggregationTest { + ObjectMapper mapper = new ObjectMapper(); + + @Test + public void testFullSet() { + String input = "{\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\",\r\n \"time-zone\": \"-01:00\"\r\n}"; + + String expected = + "\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\", \"time_zone\": \"-01:00\"}"; + + DateHistogramAggregation actual; + try { + actual = mapper.readValue(input, DateHistogramAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void test2() { + String input = "{\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\"\r\n}"; + + String expected = "\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\"}"; + + DateHistogramAggregation actual; + try { + actual = mapper.readValue(input, DateHistogramAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void test3() { + String input = "{\r\n \"field\": \"mydate\"\r\n}"; + + String expected = "\"date_histogram\": {\"field\": \"mydate\"}"; + + DateHistogramAggregation actual; + try { + actual = mapper.readValue(input, DateHistogramAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java new file mode 100644 index 0000000..45e7c51 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class DateRangeAggregationTest { + + private static ObjectMapper mapper = new ObjectMapper(); + + + @Test + public void test() { + + String input = + "{\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\"\r\n }\r\n ],\r\n \"format\": \"MM-yyy\",\r\n \"size\": \"5\"\r\n}"; + String expected = + "\"date_range\": {\"field\": \"mydate\", \"format\": \"MM-yyy\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"from\": \"2016-12-19T00:00:00.738-05:00\"}], \"size\": 5}"; + + DateRangeAggregation actual; + try { + actual = mapper.readValue(input, DateRangeAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void testNoFormatNoSize() { + + String input = + "{\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\"\r\n }\r\n ]\r\n}"; + String expected = + "\"date_range\": {\"field\": \"mydate\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"from\": \"2016-12-19T00:00:00.738-05:00\"}]}"; + + DateRangeAggregation actual; + try { + actual = mapper.readValue(input, DateRangeAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java new file mode 100644 index 0000000..ef7325e --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java @@ -0,0 +1,75 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class DateRangeTest { + private static ObjectMapper mapper = new ObjectMapper(); + + @Test + public void testBoth() { + String input = + "{\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n}"; + String expected = "{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}"; + + DateRange actual; + try { + actual = mapper.readValue(input, DateRange.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void testFrom() { + String input = "{\"from\": \"2016-12-19T00:00:00.738-05:00\"}"; + String expected = "{\"from\": \"2016-12-19T00:00:00.738-05:00\"}"; + + DateRange actual; + try { + actual = mapper.readValue(input, DateRange.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void testTo() { + String input = "{\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n}"; + String expected = "{\"to\": \"2016-12-23T23:59:59.738-05:00\"}"; + + DateRange actual; + try { + actual = mapper.readValue(input, DateRange.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java new file mode 100644 index 0000000..81fa07f --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.junit.Test; + +public class FilterTest { + + @Test + public void test() throws JsonParseException, JsonMappingException, IOException { + + + String json = "{ \"any\": [ " + "{\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}," + + "{\"match\": {\"field\": \"searchTags\", \"value\": \"b\"}}" + "]," + "\"all\": [" + + "{\"parsed-query\": {\"field\": \"fieldname\", \"query-string\": \"string\"}}" + "]" + "}"; + + ObjectMapper mapper = new ObjectMapper(); + Filter filter = mapper.readValue(json, Filter.class); + System.out.println("GDF: filter = " + filter); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java new file mode 100644 index 0000000..1ebed91 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java @@ -0,0 +1,62 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +public class GroupByAggregationTest { + private static ObjectMapper mapper = new ObjectMapper(); + + @Test + public void test() { + String input = "{\"field\" : \"entityType\", \"size\": 20}\r\n"; + + String expected = "\"terms\": {\"field\": \"entityType\", \"size\": 20}"; + + GroupByAggregation actual; + try { + actual = mapper.readValue(input, GroupByAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + + @Test + public void testNoSize() { + String input = "{\"field\" : \"entityType\"}\r\n"; + + String expected = "\"terms\": {\"field\": \"entityType\"}"; + + GroupByAggregation actual; + try { + actual = mapper.readValue(input, GroupByAggregation.class); + assertEquals(expected, actual.toElasticSearch()); + } catch (Exception e) { + fail("Exception occurred: " + e.getMessage()); + } + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java new file mode 100644 index 0000000..1f4887f --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java @@ -0,0 +1,368 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.junit.Test; + +public class QueryTest { + + /** + * This test validates that we are able to marshal json structures representing term queries into POJOs and that we + * can then unmarshal those POJOs into ElasticSearch syntax. + * + * @throws JsonParseException + * @throws JsonMappingException + * @throws IOException + */ + @Test + public void termQueryTest() throws JsonParseException, JsonMappingException, IOException { + + Integer intValue = 1; + String field = "searchTags"; + String termQueryWithIntegerValueJson = "{\"field\": \"" + field + "\", \"value\": " + intValue + "}"; + String termQueryWithIntegerValueExpectedES = "{\"term\": {\"" + field + "\" : " + intValue + "}}"; + + Double doubleValue = 5.7; + String termQueryWithDoubleValueJson = "{\"field\": \"" + field + "\", \"value\": " + doubleValue + "}"; + String termQueryWithDoubleValueExpectedES = "{\"term\": {\"" + field + "\" : " + doubleValue + "}}"; + + String stringValue = "theValue"; + String termQueryWithStringValueJson = "{\"field\": \"" + field + "\", \"value\": \"" + stringValue + "\"}"; + String termQueryWithStringValueExpectedES = "{\"term\": {\"" + field + "\" : \"" + stringValue + "\"}}"; + + ObjectMapper mapper = new ObjectMapper(); + + + // Validate that we can marshal a term query where the supplied value + // is an Integer. + TermQuery integerTermQuery = mapper.readValue(termQueryWithIntegerValueJson, TermQuery.class); + assertTrue( + "Expected value to be of type Integer, but was type " + + integerTermQuery.getValue().getClass().getName(), + integerTermQuery.getValue() instanceof Integer); + assertEquals(intValue, integerTermQuery.getValue()); + + assertTrue("ElasticSearch term query translation does not match the expected result", + termQueryWithIntegerValueExpectedES.equals(integerTermQuery.toElasticSearch())); + + // Validate that we can marshal a term query where the supplied value + // is a Double. + TermQuery doubleTermQuery = mapper.readValue(termQueryWithDoubleValueJson, TermQuery.class); + assertTrue( + "Expected value to be of type Double, but was type " + doubleTermQuery.getValue().getClass().getName(), + doubleTermQuery.getValue() instanceof Double); + assertEquals(doubleValue, doubleTermQuery.getValue()); + assertTrue("ElasticSearch term query translation does not match the expected result", + termQueryWithDoubleValueExpectedES.equals(doubleTermQuery.toElasticSearch())); + + // Validate that we can marshal a term query where the supplied value + // is a String literal. + TermQuery stringTermQuery = mapper.readValue(termQueryWithStringValueJson, TermQuery.class); + assertTrue( + "Expected value to be of type String, but was type " + stringTermQuery.getValue().getClass().getName(), + stringTermQuery.getValue() instanceof String); + assertEquals(stringValue, stringTermQuery.getValue()); + assertTrue("ElasticSearch term query translation does not match the expected result", + termQueryWithStringValueExpectedES.equals(stringTermQuery.toElasticSearch())); + + + } + + + /** + * This test validates that we are able to marshal json structures representing parsed queries into POJOs and that + * we can then unmarshal those POJOs into ElasticSearch syntax. + * + * @throws JsonParseException + * @throws JsonMappingException + * @throws IOException + */ + @Test + public void parsedQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "fieldname"; + String queryString = "The query string"; + + String queryJson = "{\"field\": \"" + field + "\", \"query-string\": \"" + queryString + "\"}"; + String queryExpectedES = + "{\"query_string\": {\"default_field\": \"" + field + "\", \"query\": \"" + queryString + "\"}}"; + + ObjectMapper mapper = new ObjectMapper(); + ParsedQuery pq = mapper.readValue(queryJson, ParsedQuery.class); + + assertTrue("Unexpected marshalled value for 'field' - expected: " + field + " actual: " + pq.getField(), + field.equals(pq.getField())); + assertTrue("Unexpected marshalled value for 'query-string' - expected: " + queryString + " actual: " + + pq.getQueryString(), queryString.equals(pq.getQueryString())); + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + queryExpectedES + " Actual: " + pq.toElasticSearch(), + queryExpectedES.equals(pq.toElasticSearch())); + } + + + /** + * This test validates that a ranged query cannot be parsed with values for both the 'gte' and 'gt' fields or the + * 'lte' and 'lt' fields, and that we do not allow mixing of numeric and date types in the same query. + * + * @throws JsonParseException + * @throws IOException + */ + @Test + public void rangeQueryConflictingBoundsTest() throws JsonParseException, IOException { + + String invalidGTAndGTE = + "{ \"field\": \"timestamp\", \"gte\": \"2016-10-06T00:00:00.558+03:00\", \"gt\": \"2016-10-06T23:59:59.558+03:00\"}"; + String invalidLTAndLTE = + "{ \"field\": \"timestamp\", \"lte\": \"2016-10-06T00:00:00.558+03:00\", \"lt\": \"2016-10-06T23:59:59.558+03:00\"}"; + String invalidTypes = "{ \"field\": \"timestamp\", \"lte\": 5, \"gte\": \"2016-10-06T23:59:59.558+03:00\"}"; + + ObjectMapper mapper = new ObjectMapper(); + + // Attempt to parse a query where we are setting values for both the + // 'greater than' and 'greater than and equal to' operators. + boolean gotExpectedException = false; + try { + mapper.readValue(invalidGTAndGTE, RangeQuery.class); + } catch (JsonMappingException e) { + gotExpectedException = true; + } + assertTrue("Attempting to set both a 'gt' and 'gte' value on the same query should not have been allowed", + gotExpectedException); + + // Attempt to parse a query where we are setting values for both the + // 'less than' and 'less than and equal to' operators. + gotExpectedException = false; + try { + mapper.readValue(invalidLTAndLTE, RangeQuery.class); + } catch (JsonMappingException e) { + gotExpectedException = true; + } + assertTrue("Attempting to set both a 'lt' and 'lte' value on the same query should not have been allowed", + gotExpectedException); + + // Attempt to parse a query where we are mixing numeric and date values + // in the same query. + gotExpectedException = false; + try { + mapper.readValue(invalidTypes, RangeQuery.class); + } catch (JsonMappingException e) { + gotExpectedException = true; + } + assertTrue("Attempting to mix numeric and date values in the same query should not have been allowed", + gotExpectedException); + + + } + + + /** + * This test validates that date range queries can be marshalled to a Java POJO and unmarshalled to ElasticSearch + * syntax. + * + * @throws JsonParseException + * @throws JsonMappingException + * @throws IOException + */ + @Test + public void dateRangeQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "timestamp"; + String greaterThanDate = "2016-10-06T00:00:00.558+03:00"; + String lessThanDate = "2016-10-06T23:59:59.558+03:00"; + + ObjectMapper mapper = new ObjectMapper(); + + // Generate a date range query using 'greater than or equal' and 'less + // than or equal' operations. + String dateRangeJson = "{ \"field\": \"" + field + "\", \"gte\": \"" + greaterThanDate + "\", \"lte\": \"" + + lessThanDate + "\"}"; + String dateRangeExpectedES = + "{\"range\": {\"timestamp\": {\"gte\": \"2016-10-06T00:00:00.558+03:00\", \"lte\": \"2016-10-06T23:59:59.558+03:00\"}}}"; + + // Validate that the query is marshalled correctly to the POJO and that + // the generated ElasticSearch syntax looks as expected. + RangeQuery dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); + + assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " + + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); + assertTrue("Unexpected type for 'gte' value. Expected: String Actual: " + + dateRangeQuery.getGte().getClass().getName(), dateRangeQuery.getGte() instanceof String); + assertTrue("Unexpected type for 'lte' value. Expected: String Actual: " + + dateRangeQuery.getLte().getClass().getName(), dateRangeQuery.getLte() instanceof String); + assertTrue("Unexpected marshalled value for 'gte'. Expected: " + greaterThanDate + " Actual: " + + dateRangeQuery.getGte(), greaterThanDate.equals(dateRangeQuery.getGte())); + assertTrue("Unexpected marshalled value for 'lte'. Expected: " + lessThanDate + " Actual: " + + dateRangeQuery.getLte(), lessThanDate.equals(dateRangeQuery.getLte())); + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " + + dateRangeQuery.toElasticSearch(), + dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); + + + // Generate a date range query using 'greater than' and 'less than or + // equal' operations. + dateRangeJson = "{ \"field\": \"" + field + "\", \"gt\": \"" + greaterThanDate + "\", \"lte\": \"" + + lessThanDate + "\"}"; + dateRangeExpectedES = + "{\"range\": {\"timestamp\": {\"gt\": \"2016-10-06T00:00:00.558+03:00\", \"lte\": \"2016-10-06T23:59:59.558+03:00\"}}}"; + + // Validate that the query is marshalled correctly to the POJO and that + // the generated ElasticSearch syntax looks as expected. + dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); + + assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " + + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); + + assertTrue("Unexpected type for 'gt' value. Expected: String Actual: " + + dateRangeQuery.getGt().getClass().getName(), dateRangeQuery.getGt() instanceof String); + + assertTrue("Unexpected type for 'lte' value. Expected: String Actual: " + + dateRangeQuery.getLte().getClass().getName(), dateRangeQuery.getLte() instanceof String); + + assertTrue("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDate + " Actual: " + + dateRangeQuery.getGt(), greaterThanDate.equals(dateRangeQuery.getGt())); + + assertTrue("Unexpected marshalled value for 'lte'. Expected: " + lessThanDate + " Actual: " + + dateRangeQuery.getLte(), lessThanDate.equals(dateRangeQuery.getLte())); + + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " + + dateRangeQuery.toElasticSearch(), + dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); + + + // Generate a date range query using only a 'greater than' operation. + dateRangeJson = "{ \"field\": \"" + field + "\", \"gt\": \"" + greaterThanDate + "\"}"; + dateRangeExpectedES = "{\"range\": {\"timestamp\": {\"gt\": \"2016-10-06T00:00:00.558+03:00\"}}}"; + + // Validate that the query is marshalled correctly to the POJO and that + // the generated ElasticSearch syntax looks as expected. + dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); + + assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " + + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); + + assertTrue("Unexpected type for 'gt' value. Expected: String Actual: " + + dateRangeQuery.getGt().getClass().getName(), dateRangeQuery.getGt() instanceof String); + + assertTrue("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDate + " Actual: " + + dateRangeQuery.getGt(), greaterThanDate.equals(dateRangeQuery.getGt())); + + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " + + dateRangeQuery.toElasticSearch(), + dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); + + } + + /** + * This test validates that numeric range queries can be marshalled to a Java POJO and unmarshalled to ElasticSearch + * syntax. + * + * @throws JsonParseException + * @throws JsonMappingException + * @throws IOException + */ + @Test + public void numericRangeQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "version"; + Integer greaterThanInt = 5; + Integer lessThanInt = 100; + + ObjectMapper mapper = new ObjectMapper(); + + // Generate a numeric range query using 'greater than or equal' and 'less + // than or equal' operations. + String numericRangeJson = + "{ \"field\": \"" + field + "\", \"gte\": " + greaterThanInt + ", \"lte\": " + lessThanInt + "}"; + String numericRangeExpectedES = + "{\"range\": {\"" + field + "\": {\"gte\": " + greaterThanInt + ", \"lte\": " + lessThanInt + "}}}"; + + // Validate that the query is marshalled correctly to the POJO and that + // the generated ElasticSearch syntax looks as expected. + RangeQuery numericRangeQuery = mapper.readValue(numericRangeJson, RangeQuery.class); + + assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " + + numericRangeQuery.getField(), field.equals(numericRangeQuery.getField())); + assertTrue( + "Unexpected type for 'gte' value. Expected: Integer Actual: " + + numericRangeQuery.getGte().getClass().getName(), + numericRangeQuery.getGte() instanceof Integer); + assertTrue( + "Unexpected type for 'lte' value. Expected: Integer Actual: " + + numericRangeQuery.getLte().getClass().getName(), + numericRangeQuery.getLte() instanceof Integer); + assertEquals("Unexpected marshalled value for 'gte'. Expected: " + greaterThanInt + " Actual: " + + numericRangeQuery.getGte(), greaterThanInt, numericRangeQuery.getGte()); + assertEquals("Unexpected marshalled value for 'lte'. Expected: " + lessThanInt + " Actual: " + + numericRangeQuery.getLte(), lessThanInt, numericRangeQuery.getLte()); + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + numericRangeExpectedES + " Actual: " + + numericRangeQuery.toElasticSearch(), + numericRangeExpectedES.equals(numericRangeQuery.toElasticSearch())); + + + Double greaterThanDouble = 5.0; + Double lessThanDouble = 100.0; + + // Generate a date range query using 'greater than' and 'less than or + // equal' operations. + numericRangeJson = + "{ \"field\": \"" + field + "\", \"gt\": " + greaterThanDouble + ", \"lte\": " + lessThanDouble + "}"; + numericRangeExpectedES = "{\"range\": {\"" + field + "\": {\"gt\": " + greaterThanDouble + ", \"lte\": " + + lessThanDouble + "}}}"; + + // Validate that the query is marshalled correctly to the POJO and that + // the generated ElasticSearch syntax looks as expected. + numericRangeQuery = mapper.readValue(numericRangeJson, RangeQuery.class); + + assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " + + numericRangeQuery.getField(), field.equals(numericRangeQuery.getField())); + + assertTrue("Unexpected type for 'gt' value. Expected: Double Actual: " + + numericRangeQuery.getGt().getClass().getName(), numericRangeQuery.getGt() instanceof Double); + + assertTrue( + "Unexpected type for 'lte' value. Expected: Double Actual: " + + numericRangeQuery.getLte().getClass().getName(), + numericRangeQuery.getLte() instanceof Double); + + assertEquals("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDouble + " Actual: " + + numericRangeQuery.getGt(), greaterThanDouble, numericRangeQuery.getGt()); + + assertEquals("Unexpected marshalled value for 'lte'. Expected: " + lessThanDouble + " Actual: " + + numericRangeQuery.getLte(), lessThanDouble, numericRangeQuery.getLte()); + + assertTrue( + "Unexpected ElasticSearch syntax. Expected: " + numericRangeExpectedES + " Actual: " + + numericRangeQuery.toElasticSearch(), + numericRangeExpectedES.equals(numericRangeQuery.toElasticSearch())); + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java new file mode 100644 index 0000000..e58e545 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java @@ -0,0 +1,155 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import org.junit.Assert; +import org.junit.Test; +import org.onap.aai.sa.rest.TestUtils; + +public class RangeQueryTest { + + static { + // Set the location of the payload translation JSON file. + System.setProperty("CONFIG_HOME", "src/test/resources/json"); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetGt() { + RangeQuery rq = new RangeQuery(); + rq.setLt(new String("2x")); + Assert.assertEquals("2x", rq.getLt()); + Assert.assertNotNull(rq.toElasticSearch()); + Assert.assertNotNull(rq.toString()); + rq.setGt(new Integer(1)); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetGte() { + RangeQuery rq = new RangeQuery(); + rq.setGt(new Integer(1)); + Assert.assertNotNull(rq.toElasticSearch()); + Assert.assertNotNull(rq.toString()); + rq.setGte(new Integer(1)); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetLt() { + RangeQuery rq = new RangeQuery(); + rq.setLt(new Integer(1)); + rq.setFormat("format-1"); + assertThat(rq.getFormat(), is(equalTo("format-1"))); + Assert.assertNotNull(rq.toElasticSearch()); + Assert.assertNotNull(rq.toString()); + + rq.setGt(new Integer(1)); + Assert.assertNotNull(rq.toElasticSearch()); + Assert.assertNotNull(rq.toString()); + rq.setLt(new String("10")); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetLte() { + RangeQuery rq = new RangeQuery(); + rq.setGt(new Integer(1)); + rq.setTimeZone("CT"); + assertThat(rq.getTimeZone(), is(equalTo("CT"))); + Assert.assertNotNull(rq.toElasticSearch()); + Assert.assertNotNull(rq.toString()); + + rq.setLte(new String("10")); + } + + @Test + public void testSearchStatementAggregations() throws IOException { + File queryWithSubrangeFile = new File("src/test/resources/json/queries/query-with-subrange.json"); + String queryWithSubrangeStr = TestUtils.readFileToString(queryWithSubrangeFile); + + ObjectMapper mapper = new ObjectMapper(); + SearchStatement ss = mapper.readValue(queryWithSubrangeStr, SearchStatement.class); + + Aggregation a1 = getAggregationObject(); + Aggregation a2 = getAggregationObject(); + Aggregation[] aggs = new Aggregation[] {a1, a2}; + ss.setAggregations(aggs); + Assert.assertNotNull(ss.toString()); + } + + private Aggregation getAggregationObject() { + Aggregation a = new Aggregation(); + + AggregationStatement as = new AggregationStatement(); + DateHistogramAggregation dha = new DateHistogramAggregation(); + dha.setField("field-1"); + dha.setInterval("interval-1"); + assertThat(dha.getInterval(), is(equalTo("interval-1"))); + dha.setTimeZone("CT"); + assertThat(dha.getTimeZone(), is(equalTo("CT"))); + dha.setFormat("format-1"); + assertThat(dha.getFormat(), is(equalTo("format-1"))); + dha.setSize(10); + dha.setMinThreshold(1); + Assert.assertNotNull(dha.toElasticSearch()); + Assert.assertNotNull(dha.toString()); + as.setDateHist(dha); + as.toString(); + + as.getNestedPath(); + + DateRangeAggregation dra = new DateRangeAggregation(); + dra.setField("field-1"); + dra.setMinThreshold(1); + dra.setFormat("format-1"); + assertThat(dra.getFormat(), is(equalTo("format-1"))); + DateRange dr = new DateRange(); + dr.setFromDate("01-12-2017"); + assertThat(dr.getFromDate(), is(equalTo("01-12-2017"))); + dr.setToDate("21-12-2017"); + assertThat(dr.getToDate(), is(equalTo("21-12-2017"))); + DateRange[] drs = {dr}; + dra.setDateRanges(drs); + Assert.assertTrue(dra.getDateRanges().length == 1); + Assert.assertNotNull(dra.toElasticSearch()); + Assert.assertNotNull(dra.toString()); + as.setDateRange(dra); + as.toString(); + + as.getNestedPath(); + + GroupByAggregation gba = new GroupByAggregation(); + gba.setField("field-1"); + gba.setMinThreshold(1); + Assert.assertNotNull(gba.toElasticSearch()); + Assert.assertNotNull(gba.toString()); + as.setGroupBy(gba); + Assert.assertNotNull(as.toString()); + + a.setStatement(as); + Assert.assertNotNull(a.toString()); + return a; + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java new file mode 100644 index 0000000..45ad666 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java @@ -0,0 +1,211 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import org.junit.Test; +import org.onap.aai.sa.rest.TestUtils; + +public class SearchStatementTest { + + @Test + public void simpleQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "searchTags"; + String queryString = "aai3255"; + String queryJson = "{" + "\"queries\": [" + "{\"may\": {\"parsed-query\": {" + "\"field\": \"" + field + "\"," + + "\"query-string\": \"" + queryString + "\"}}}" + "]" + "}" + "}"; + + String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " + + "\"should\": [" + "{\"query_string\": {\"default_field\": \"searchTags\", \"query\": \"aai3255\"}}" + + "]," + "\"must_not\": []}" + "}" + "}"; + + // Marshal our simple query JSON to a SearchStatement object. + ObjectMapper mapper = new ObjectMapper(); + SearchStatement ss = mapper.readValue(queryJson, SearchStatement.class); + + // We expect to have a search statement with one query. + assertEquals("Unexpected number of queries in marshalled result", 1, ss.getQueries().length); + + // Validate that the query is of the expected type and contains the + // expected values. + QueryStatement query = ss.getQueries()[0].getQueryStatement(); + assertNotNull("Expected marshalled statement to contain a 'parsed query'", query.getParsedQuery()); + assertTrue("Unexpected field name in marshalled query. Expected: " + field + " Actual: " + + query.getParsedQuery().getField(), field.equals(query.getParsedQuery().getField())); + assertTrue( + "Unexpected query string in marshalled query. Expected: " + queryString + " Actual: " + + query.getParsedQuery().getQueryString(), + queryString.equals(query.getParsedQuery().getQueryString())); + + // Validate that we are able to produce the expected ElasticSearch + // query syntax from the search statement. + assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), + queryES.equals(ss.toElasticSearch())); + } + + + @Test + public void simpleSortedQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "searchTags"; + String queryString = "aai3255"; + String queryJson = "{" + "\"queries\": [" + "{\"may\": {\"parsed-query\": {" + "\"field\": \"" + field + "\"," + + "\"query-string\": \"" + queryString + "\"}}}" + "]," + + "\"sort\": { \"field\": \"date\", \"order\": \"ascending\" }" + "}"; + + + String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " + + "\"should\": [" + "{\"query_string\": {\"default_field\": \"searchTags\", \"query\": \"aai3255\"}}" + + "]," + "\"must_not\": []" + "}" + "}, " + "\"sort\": { \"date\": { \"order\": \"asc\"}}" + "}"; + + // Marshal our simple query JSON to a SearchStatement object. + ObjectMapper mapper = new ObjectMapper(); + SearchStatement ss = mapper.readValue(queryJson, SearchStatement.class); + + // We expect to have a search statement with one query. + assertEquals("Unexpected number of queries in marshalled result", 1, ss.getQueries().length); + + // Validate that the query is of the expected type and contains the + // expected values. + QueryStatement query = ss.getQueries()[0].getQueryStatement(); + assertNotNull("Expected marshalled statement to contain a 'parsed query'", query.getParsedQuery()); + assertTrue("Unexpected field name in marshalled query. Expected: " + field + " Actual: " + + query.getParsedQuery().getField(), field.equals(query.getParsedQuery().getField())); + assertTrue( + "Unexpected query string in marshalled query. Expected: " + queryString + " Actual: " + + query.getParsedQuery().getQueryString(), + queryString.equals(query.getParsedQuery().getQueryString())); + System.out.println("GDF: ES = " + ss.toElasticSearch()); + // Validate that we are able to produce the expected ElasticSearch + // query syntax from the search statement. + assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), + queryES.equals(ss.toElasticSearch())); + assertNull(ss.getAggregations()); + } + + @Test + public void filteredQueryTest() throws JsonParseException, JsonMappingException, IOException { + + String filterField1 = "field1"; + String filterField2 = "field2"; + String filterField3 = "field3"; + String filterValue1 = "a"; + String filterValue2 = "b"; + String filterValue3 = "string"; + String filterJson = "{ \"any\": [ " + "{\"match\": {\"field\": \"" + filterField1 + "\", \"value\": \"" + + filterValue1 + "\"}}," + "{\"match\": {\"field\": \"" + filterField2 + "\", \"value\": \"" + + filterValue2 + "\"}}" + "]," + "\"all\": [" + "{\"parsed-query\": {\"field\": \"" + filterField3 + + "\", \"query-string\": \"" + filterValue3 + "\"}}" + "]" + "}"; + + String filterStanzaJson = "\"filter\": " + filterJson; + + String queryStanzaJson = "\"queries\": [ " + + "{\"may\": {\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}}," + + "{\"may\": {\"match\": {\"field\": \"searchTags\", \"value\": \"b\"}}}," + + "{\"may\": {\"parsed-query\": {\"field\": \"fieldname\", \"query-string\": \"string\"}}}" + "]"; + + String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " + + "\"should\": [" + "{\"term\": {\"searchTags\" : \"a\"}}, " + "{\"term\": {\"searchTags\" : \"b\"}}, " + + "{\"query_string\": {\"default_field\": \"fieldname\", \"query\": \"string\"}}" + "]," + + "\"must_not\": [], " + "\"filter\": {" + "\"bool\": {" + "\"must\": [" + + "{\"query_string\": {\"default_field\": \"field3\", \"query\": \"string\"}}" + "]," + + "\"must_not\": []," + "\"should\": [" + "{\"term\": {\"field1\" : \"a\"}}, " + + "{\"term\": {\"field2\" : \"b\"}}" + "]," + "\"must_not\": []" + "}" + "}" + "}" + "}" + "}"; + + StringBuilder sb = new StringBuilder(); + sb.append("{"); + sb.append(filterStanzaJson).append(", "); + sb.append(queryStanzaJson); + sb.append("}"); + + ObjectMapper mapper = new ObjectMapper(); + SearchStatement ss = mapper.readValue(sb.toString(), SearchStatement.class); + + assertEquals("Unexpected number of queries in the 'any' list for this statement's filter", 2, + ss.getFilter().getAny().length); + assertEquals("Unexpected number of queries in the 'all' list for this statement's filter", 1, + ss.getFilter().getAll().length); + + assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), + queryES.equals(ss.toElasticSearch())); + + assertNull(ss.getAggregations()); + } + + @Test + public void aggregationTest() { + String input = + "{\r\n \"queries\": [\r\n {\r\n \"must\": {\r\n \"match\": {\r\n \"field\": \"searchTags\",\r\n \"value\": \"a\"\r\n }\r\n }\r\n }\r\n ],\r\n \"aggregations\": [\r\n {\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ]\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byTerm\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"myterm\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-histogram\": {\r\n \"field\": \"myDate\",\r\n \"interval\": \"myInterval\"\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n },\r\n {\r\n \"name\": \"2nd\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"anotherTerm\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; + + ObjectMapper mapper = new ObjectMapper(); + try { + SearchStatement ss = mapper.readValue(input, SearchStatement.class); + Aggregation[] aggs = ss.getAggregations(); + assertNotNull(aggs); + assertEquals("Unexpected number aggregations", 2, aggs.length); + assertEquals("byDate", aggs[0].getName()); + assertNotNull(aggs[0].getStatement().getDateRange()); + assertEquals("mydate", aggs[0].getStatement().getDateRange().getField()); + assertNotNull(aggs[0].getStatement().getSubAggregations()); + assertEquals(2, aggs[0].getStatement().getSubAggregations().length); + assertEquals("byTerm", aggs[0].getStatement().getSubAggregations()[0].getName()); + assertEquals("byDate", aggs[0].getStatement().getSubAggregations()[1].getName()); + assertNull(aggs[0].getStatement().getGroupBy()); + assertEquals("2nd", aggs[1].getName()); + assertNotNull(aggs[1].getStatement().getGroupBy()); + assertEquals("anotherTerm", aggs[1].getStatement().getGroupBy().getField()); + assertNull(aggs[1].getStatement().getDateRange()); + assertNull(aggs[1].getStatement().getSubAggregations()); + + } catch (Exception e) { + fail("Encountered exception: " + e.getMessage()); + } + } + + @Test + public void resultSetRangeTest() throws IOException { + + // Simple query with a result set subrange specified. + File queryWithSubrangeFile = new File("src/test/resources/json/queries/query-with-subrange.json"); + String queryWithSubrangeStr = TestUtils.readFileToString(queryWithSubrangeFile); + String queryWithSubrangeExpectedESString = + "{\"version\": true,\"from\": 0, \"size\": 10, \"query\": {\"bool\": {\"must\": [{\"term\": {\"field1\" : \"Bob\"}}], \"should\": [],\"must_not\": []}}}"; + + ObjectMapper mapper = new ObjectMapper(); + SearchStatement ss = mapper.readValue(queryWithSubrangeStr, SearchStatement.class); + + assertEquals("Unexpected index for result set start", ss.getFrom(), (Integer) 0); + assertEquals("Unexpected value for result set size", ss.getSize(), (Integer) 10); + assertTrue("Unexpected elastic search query generated from search statement", + ss.toElasticSearch().equals(queryWithSubrangeExpectedESString)); + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java new file mode 100644 index 0000000..832fa98 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java @@ -0,0 +1,49 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.junit.Test; + +public class SortTest { + + @Test + public void sortFieldTest() throws JsonParseException, JsonMappingException, IOException { + + String field = "fieldname"; + String order = "ascending"; + String json = "{\"field\": \"" + field + "\", \"order\": \"" + order + "\"}"; + + ObjectMapper mapper = new ObjectMapper(); + Sort sort = mapper.readValue(json, Sort.class); + + assertTrue("Unexpected field name in marshalled object. Expected: " + field + " Actual: " + sort.getField(), + field.equals(sort.getField())); + assertTrue("Unexpected order field in marshalled object. Expected: " + order + " Actual: " + sort.getOrder(), + order.equals(sort.getOrder().toString())); + + } +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java new file mode 100644 index 0000000..9eab5f4 --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.searchapi; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import org.junit.Assert; +import org.junit.Test; + +public class TermQueryTest { + + @Test + public void testAllMethods() throws IOException { + String field = "searchTags.nested"; + String stringValue = "theValue.nested"; + String termQueryWithStringValueJson = "{\"field\": \"" + field + "\", \"value\": \"" + stringValue + "\"}"; + + ObjectMapper mapper = new ObjectMapper(); + TermQuery stringTermQuery = mapper.readValue(termQueryWithStringValueJson, TermQuery.class); + Assert.assertEquals(stringValue, stringTermQuery.getValue()); + Assert.assertEquals("searchTags.nested", stringTermQuery.getField()); + stringTermQuery.setOperator("operator-1"); + Assert.assertEquals("operator-1", stringTermQuery.getOperator()); + stringTermQuery.setSearchAnalyzer("search-1"); + Assert.assertEquals("search-1", stringTermQuery.getSearchAnalyzer()); + + String field1 = "searchTags-1 searchTags.second"; + String stringValue1 = "theValue-1 theValue.second"; + String multiFieldTermQueryJSon = "{\"field\": \"" + field1 + "\", \"value\": \"" + stringValue1 + "\"}"; + TermQuery multiFieldTermQuery = mapper.readValue(multiFieldTermQueryJSon, TermQuery.class); + multiFieldTermQuery.setOperator("and"); + multiFieldTermQuery.setSearchAnalyzer("search-1"); + Assert.assertNotNull(multiFieldTermQuery.toElasticSearch()); + Assert.assertNotNull(multiFieldTermQuery.pathForNestedField(field1)); + + String field2 = "search11 search2"; + String stringValue2 = "theValue1 theValue2"; + String multiFieldTermJSon = "{\"field\": \"" + field2 + "\", \"value\": \"" + stringValue2 + "\"}"; + TermQuery multiFieldTerm = mapper.readValue(multiFieldTermJSon, TermQuery.class); + multiFieldTerm.setOperator("or"); + multiFieldTerm.setSearchAnalyzer("search-1"); + Assert.assertNotNull(multiFieldTerm.toElasticSearch()); + } + +} diff --git a/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java new file mode 100644 index 0000000..877b64f --- /dev/null +++ b/search-data-service/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 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========================================================= + */ +package org.onap.aai.sa.searchdbabstraction.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import org.apache.commons.io.IOUtils; +import org.junit.Before; +import org.junit.Test; + +public class ElasticSearchPayloadTranslatorTest { + + private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/index-mapping.json"; + + @Before + public void setup() throws Exception { + System.setProperty("CONFIG_HOME", System.getProperty("user.dir") + File.separator + "src/test/resources/json"); + } + + @Test + public void testPayloadTranslation() throws Exception { + String expectedErrMsg = "Sample error message for whitespace check"; + File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); + String documentJson = IOUtils.toString(new FileInputStream(schemaFile), "UTF-8"); + assertTrue(documentJson.contains("\"type\": \"string\"")); + assertTrue(documentJson.contains("\"index\": \"analyzed\"")); + String translatedPayload = ElasticSearchPayloadTranslator.translateESPayload(documentJson); + assertTrue(translatedPayload.contains("\"type\":\"text\"")); + assertTrue(translatedPayload.contains("\"index\":true")); + assertTrue(translatedPayload.contains("\"fielddata\":true")); + assertFalse(documentJson.contains("\"index\":\"analyzed\"")); + assertTrue(translatedPayload.contains("\"errMsg\":\"" + expectedErrMsg + "\"")); + } +} diff --git a/search-data-service/src/test/resources/json/analysis-config.json b/search-data-service/src/test/resources/json/analysis-config.json new file mode 100644 index 0000000..a622dcf --- /dev/null +++ b/search-data-service/src/test/resources/json/analysis-config.json @@ -0,0 +1,21 @@ +[ + { + "name": "nGram_analyzer", + "description": "NGram Analyzer", + "tokenizer": "whitespace", + "filters": [ + "lowercase", + "asciifolding", + "nGram_filter" + ] + }, + { + "name": "whitespace_analyzer", + "description": "Whitespace Analyzer", + "tokenizer": "whitespace", + "filters": [ + "lowercase", + "asciifolding" + ] + } +] \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/bulk-ops-invalid.json b/search-data-service/src/test/resources/json/bulk-ops-invalid.json new file mode 100644 index 0000000..4708498 --- /dev/null +++ b/search-data-service/src/test/resources/json/bulk-ops-invalid.json @@ -0,0 +1,32 @@ +{ + "operations": [ + { + "operation": "create", + "meta-data": { + "index": "test-index" + }, + "document": { + "field1": "value1", + "field2": "value2" + } + }, + { + "operation": "dance!", + "meta-data": { + "index": "test-index", + "id": "2", + "version": "5" + }, + "document": { + "field1": "new-value" + } + }, + { + "operation": "delete", + "meta-data": { + "index": "test-index", + "id": "4" + } + } + ] +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/bulk-ops-valid.json b/search-data-service/src/test/resources/json/bulk-ops-valid.json new file mode 100644 index 0000000..6e805cf --- /dev/null +++ b/search-data-service/src/test/resources/json/bulk-ops-valid.json @@ -0,0 +1,31 @@ +[ + { + "create": { + "metaData": { + "url": "/indexes/test-index/documents/" + }, + "document": { + "field1": "value1", + "field2": "value2" + } + } + }, + { + "update": { + "metaData": { + "url": "/indexes/test-index/documents/3", + "etag": "5" + }, + "document": { + "field1": "new-value" + } + } + }, + { + "delete": { + "metaData": { + "url": "/indexes/test-index/documents/7" + } + } + } +] diff --git a/search-data-service/src/test/resources/json/dynamic-custom-template.json b/search-data-service/src/test/resources/json/dynamic-custom-template.json new file mode 100644 index 0000000..a7bd5ae --- /dev/null +++ b/search-data-service/src/test/resources/json/dynamic-custom-template.json @@ -0,0 +1,12 @@ +"dynamic_templates":[ + { + "strings":{ + "match_mapping_type":"string", + "match": "*", + "mapping":{ + "type":"text", + "fielddata":true + } + } + } +], \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/dynamicIndex.json b/search-data-service/src/test/resources/json/dynamicIndex.json new file mode 100644 index 0000000..5df4069 --- /dev/null +++ b/search-data-service/src/test/resources/json/dynamicIndex.json @@ -0,0 +1,17 @@ +{ + "mappings": { + "dynamic_templates": [{ + "strings": { + "match_mapping_type": "string", + "match": "*", + "mapping": { + "type": "string", + "index": "not_analyzed" + } + } + } + ] + } + + +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/es-payload-translation.json b/search-data-service/src/test/resources/json/es-payload-translation.json new file mode 100644 index 0000000..58ed8f6 --- /dev/null +++ b/search-data-service/src/test/resources/json/es-payload-translation.json @@ -0,0 +1,16 @@ +{ + "attr-translations": [ + { + "query": "$..[?(@.type=='string' && @.index=='analyzed')]", + "update": {"type": "text", "index": true, "fielddata": true} + }, + { + "query": "$..[?(@.type=='string' && @.index=='not_analyzed')]", + "update": {"type": "keyword", "index": true} + }, + { + "query": "$..[?(@.type=='string' && !@.index)]", + "update": {"type": "text", "fielddata": true} + } + ] +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/filter-config.json b/search-data-service/src/test/resources/json/filter-config.json new file mode 100644 index 0000000..d1de1d7 --- /dev/null +++ b/search-data-service/src/test/resources/json/filter-config.json @@ -0,0 +1,7 @@ +[ + { + "name": "nGram_filter", + "description": "Custom NGram Filter.", + "configuration": " \"type\": \"nGram\", \"min_gram\": 1, \"max_gram\": 50, \"token_chars\": [ \"letter\", \"digit\", \"punctuation\", \"symbol\" ]" + } +] \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/index-mapping.json b/search-data-service/src/test/resources/json/index-mapping.json new file mode 100644 index 0000000..e447092 --- /dev/null +++ b/search-data-service/src/test/resources/json/index-mapping.json @@ -0,0 +1,28 @@ +{ + "fields": [ + {"name": "validationId", "type": "string", "searchable": false}, + {"name": "validationTimestamp1", "type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "entityId", "type": "nested"}, + {"name": "entityType", "type": "string", "index": "analyzed"}, + {"name": "entityLink", "type": "string"}, + + {"name": "resourceVersion", "type": "string", "index": "not_analyzed"}, + {"name": "violations", "type": "nested", "sub-fields": [ + {"name": "violationId", "type": "string"}, + {"name": "violationTimestamp", "type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "modelName", "type": "string"}, + {"name": "category", "type": "string"}, + {"name": "severity", "type": "string"}, + {"name": "violationType", "type": "string"}, + {"name": "validationRule", "type": "string"}, + {"name": "violationDetails", "type": "nested", "sub-fields": [ + {"name": "entityId", "type": "nested"}, + {"name": "entityType", "type": "string"}, + {"name": "modelName", "type": "string"}, + {"name": "MISSING_REL", "type": "string"} + ]}, + {"name": "errorMessage", "type": "string", "errMsg": "Sample error message for whitespace check"} + ]} + ] + +} diff --git a/search-data-service/src/test/resources/json/nested-document.json b/search-data-service/src/test/resources/json/nested-document.json new file mode 100644 index 0000000..8373a6d --- /dev/null +++ b/search-data-service/src/test/resources/json/nested-document.json @@ -0,0 +1,49 @@ +{ + "fields": [ + { + "name": "serverName", + "data-type": "string", + "searchable": true, + "search-analyzer": "whitespace", + "sub-fields": [] + }, + { + "name": "serverComplex", + "data-type": "string", + "search-analyzer": "whitespace", + "sub-fields": [] + }, + { + "name": "address", + "data-type": "nested", + "sub-fields": [ + { + "name": "street", + "data-type": "string", + "sub-fields": [] + }, + { + "name": "city", + "data-type": "string", + "sub-fields": [] + }, + { + "name": "phone-numbers", + "data-type": "nested", + "sub-fields": [ + { + "name": "home", + "data-type": "string", + "sub-fields": [] + }, + { + "name": "cell", + "data-type": "string", + "sub-fields": [] + } + ] + } + ] + } + ] +} diff --git a/search-data-service/src/test/resources/json/queries/query-with-subrange.json b/search-data-service/src/test/resources/json/queries/query-with-subrange.json new file mode 100644 index 0000000..36e5f15 --- /dev/null +++ b/search-data-service/src/test/resources/json/queries/query-with-subrange.json @@ -0,0 +1,14 @@ +{ + "results-start": 0, + "results-size": 10, + "queries": [ + { + "must": { + "match": { + "field": "field1", + "value": "Bob" + } + } + } + ] +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/queries/simple-parsed-query.json b/search-data-service/src/test/resources/json/queries/simple-parsed-query.json new file mode 100644 index 0000000..50ce681 --- /dev/null +++ b/search-data-service/src/test/resources/json/queries/simple-parsed-query.json @@ -0,0 +1,10 @@ +{ + "queries": [ + { + "parsed-query": { + "field": "searchTags", + "query-string": "a" + } + } + ] +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/search_policy.json b/search-data-service/src/test/resources/json/search_policy.json new file mode 100644 index 0000000..b1abe3c --- /dev/null +++ b/search-data-service/src/test/resources/json/search_policy.json @@ -0,0 +1,63 @@ +{ + "roles": [ + { + "name": "testRole", + "functions": [{ + "name": "testFunction", + "methods": [{ + "name": "GET" + }, { + "name": "DELETE" + }, { + "name": "PUT" + } + ] + } + ], + "users": [{ + "username": "testUser" + } + + ] + }, + + { + "name": "devRole", + "functions": [{ + "name": "search", + "methods": [{ + "name": "GET" + }, { + "name": "DELETE" + }, { + "name": "PUT" + } + ] + } + ], + "users": [ + { + "username": "cn=onap, ou=onap, o=onap, l=ottawa, st=ontario, c=ca" + } + + ] + }, + + { + "name": "testBasicAuth", + "functions": [{ + "name": "testBasicAuthFuncyion", + "methods": [{ + "name": "GET" + } + ] + } + ], + "users": [{ + "user": "testBasicAuthUser", + "pass": "OBF:1ytc1vu91v2p1rxf1mqh1v8s1z0d1msn1san1mqf1z0h1v9u1msl1rvf1v1p1vv11yta" + } + ] + } + ] +} \ No newline at end of file diff --git a/search-data-service/src/test/resources/json/settings-config.json b/search-data-service/src/test/resources/json/settings-config.json new file mode 100644 index 0000000..5ebdbcc --- /dev/null +++ b/search-data-service/src/test/resources/json/settings-config.json @@ -0,0 +1,9 @@ +{ + "number_of_shards": "5", + "replication": "TLV_DATACENTER:2", + "drop_on_delete_index": true, + "version": { + "created": "6020399" + } +} + diff --git a/search-data-service/src/test/resources/json/simpleDocument.json b/search-data-service/src/test/resources/json/simpleDocument.json new file mode 100644 index 0000000..c21c574 --- /dev/null +++ b/search-data-service/src/test/resources/json/simpleDocument.json @@ -0,0 +1,17 @@ +{ + "fields": [ + { + "name": "serverName", + "data-type": "string", + "searchable": true, + "search-analyzer": "whitespace", + "sub-fields": [] + }, + { + "name": "serverComplex", + "data-type": "string", + "search-analyzer": "whitespace", + "sub-fields": [] + } + ] +} diff --git a/search-data-service/src/test/resources/json/tier-support-document.json b/search-data-service/src/test/resources/json/tier-support-document.json new file mode 100644 index 0000000..c6a20db --- /dev/null +++ b/search-data-service/src/test/resources/json/tier-support-document.json @@ -0,0 +1,30 @@ +{ + "document-type": "tier-support", + "document-id": "ts-1", + "fields": [ + { + "name": "entityType", + "data-type": "string" + }, + { + "name": "edgeTagQueryEntityFieldName", + "data-type": "string", + "index": false + }, + { + "name": "edgeTagQueryEntityFieldValue", + "data-type": "string", + "index": false + }, + { + "name": "searchTagIDs", + "data-type": "string" + }, + { + "name": "searchTags", + "data-type": "string", + "index-analyzer": "nGram_analyzer", + "search-analyzer": "whitespace_analyzer" + } + ] +} \ No newline at end of file diff --git a/src/main/bin/start.sh b/src/main/bin/start.sh deleted file mode 100644 index 5248a7a..0000000 --- a/src/main/bin/start.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -BASEDIR="/opt/app/search-data-service" -AJSC_HOME="$BASEDIR" -AJSC_CONF_HOME="$AJSC_HOME/bundleconfig/" - -if [ -z "$CONFIG_HOME" ]; then - echo "CONFIG_HOME must be set in order to start up process" - exit 1 -fi - -if [ -z "$KEY_STORE_PASSWORD" ]; then - echo "KEY_STORE_PASSWORD must be set in order to start up process" - exit 1 -fi - -PROPS="-DAJSC_HOME=$AJSC_HOME" -PROPS="$PROPS -DAJSC_CONF_HOME=$AJSC_CONF_HOME" -PROPS="$PROPS -Dlogging.config=$BASEDIR/bundleconfig/etc/logback.xml" -PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME" -PROPS="$PROPS -DKEY_STORE_PASSWORD=$KEY_STORE_PASSWORD" - -if [ ! -z "$TRUST_STORE_PASSWORD" ]; then - PROPS="$PROPS -DTRUST_STORE_PASSWORD=${TRUST_STORE_PASSWORD}" -fi - -if [ ! -z "$TRUST_STORE_LOCATION" ]; then - PROPS="$PROPS -DTRUST_STORE_LOCATION=${TRUST_STORE_LOCATION}" -fi - -JVM_MAX_HEAP=${MAX_HEAP:-1024} - -java $PROPS -jar $BASEDIR/search-data-service-package.jar \ No newline at end of file diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile deleted file mode 100644 index ad402b2..0000000 --- a/src/main/docker/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM ubuntu:14.04 - -ARG MICRO_HOME=/opt/app/search-data-service -ARG BIN_HOME=$MICRO_HOME/bin - -## Install and setup java8 -RUN apt-get update && apt-get install -y software-properties-common -## sudo -E is required to preserve the environment. If you remove that line, it will most like freeze at this step -RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk -## Setup JAVA_HOME, this is useful for docker commandline -ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64 -RUN export JAVA_HOME - -# Build up the deployment folder structure -RUN mkdir -p $MICRO_HOME -RUN mkdir -p $MICRO_HOME/bundleconfig/etc -ADD search-data-service* $MICRO_HOME/ -RUN mkdir -p $BIN_HOME -COPY *.sh $BIN_HOME -COPY bundleconfig-local $MICRO_HOME/bundleconfig -COPY bundleconfig-local/etc/logback.xml $MICRO_HOME/bundleconfig/etc -RUN chmod 755 $BIN_HOME/* -RUN ln -s /logs $MICRO_HOME/logs - -EXPOSE 9509 9509 - -CMD ["/opt/app/search-data-service/bin/start.sh"] diff --git a/src/main/java/org/onap/aai/sa/Application.java b/src/main/java/org/onap/aai/sa/Application.java deleted file mode 100644 index 059ca22..0000000 --- a/src/main/java/org/onap/aai/sa/Application.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa; - -import java.util.HashMap; -import org.eclipse.jetty.util.security.Password; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; - -@SpringBootApplication -public class Application extends SpringBootServletInitializer { - - public static void main(String[] args) { - String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD"); - if (keyStorePassword == null || keyStorePassword.isEmpty()) { - throw new RuntimeException("Env property KEY_STORE_PASSWORD not set"); - } - HashMap props = new HashMap<>(); - String deobfuscatedKeyStorePassword = keyStorePassword.startsWith("OBF:") ? Password.deobfuscate(keyStorePassword) : keyStorePassword; - props.put("server.ssl.key-store-password", deobfuscatedKeyStorePassword); - - String trustStoreLocation = System.getProperty("TRUST_STORE_LOCATION"); - String trustStorePassword = System.getProperty("TRUST_STORE_PASSWORD"); - if (trustStoreLocation != null && trustStorePassword != null) { - trustStorePassword = trustStorePassword.startsWith("OBF:") ? Password.deobfuscate(trustStorePassword) : trustStorePassword; - props.put("server.ssl.trust-store", trustStoreLocation); - props.put("server.ssl.trust-store-password", trustStorePassword); - } - - String requireClientAuth = System.getenv("REQUIRE_CLIENT_AUTH"); - if (requireClientAuth == null || requireClientAuth.isEmpty()) { - props.put("server.ssl.client-auth", "need"); - }else { - props.put("server.ssl.client-auth", Boolean.valueOf(requireClientAuth)? "need" : "want"); - } - - new Application().configure(new SpringApplicationBuilder(Application.class).properties(props)).run(args); - } -} diff --git a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java deleted file mode 100644 index 199b5ec..0000000 --- a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.auth; - -import javax.servlet.http.Cookie; -import org.springframework.http.HttpHeaders; - -public class SearchDbServiceAuth { - - public SearchDbServiceAuth() { // Do not instantiate - } - - public boolean authBasic(String username, String authFunction) { - return SearchDbServiceAuthCore.authorize(username, authFunction); - } - - public String authUser(HttpHeaders headers, String authUser, String authFunction) { - return new SearchDbServiceAuth().authBasic(authUser, authFunction) ? "OK" : "AAI_9101"; - } - - public boolean authCookie(Cookie cookie, String authFunction, StringBuilder username) { - if (cookie == null) { - return false; - } - return SearchDbServiceAuthCore.authorize(username.toString(), authFunction); - } -} diff --git a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java deleted file mode 100644 index 5bab0c0..0000000 --- a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.auth; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; - -public class SearchDbServiceAuthCore { - - private static Logger logger = LoggerFactory.getInstance().getLogger(SearchDbServiceAuthCore.class.getName()); - - private static String authFileName = SearchDbConstants.SDB_AUTH_CONFIG_FILENAME; - - private enum HTTP_METHODS { - POST, - GET, - PUT, - DELETE - } - - private static boolean usersInitialized = false; - private static HashMap users; - private static Timer timer = null; - - // Don't instantiate - private SearchDbServiceAuthCore() {} - - public static synchronized void init() { - if (SearchDbServiceAuthCore.authFileName == null) { - SearchDbServiceAuthCore.authFileName = "/home/aaiadmin/etc/aaipolicy.json"; - } - SearchDbServiceAuthCore.reloadUsers(); - } - - public static void cleanup() { - timer.cancel(); - } - - public static synchronized void reloadUsers() { - users = new HashMap<>(); - ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally - JSONParser parser = new JSONParser(); - try { - parser.parse(new FileReader(authFileName)); - JsonNode rootNode = mapper.readTree(new File(authFileName)); - JsonNode rolesNode = rootNode.path("roles"); - - for (JsonNode roleNode : rolesNode) { - String roleName = roleNode.path("name").asText(); - - TabularAuthRole authRole = new TabularAuthRole(); - JsonNode usersNode = roleNode.path("users"); - JsonNode functionsNode = roleNode.path("functions"); - for (JsonNode functionNode : functionsNode) { - String function = functionNode.path("name").asText(); - JsonNode methodsNode = functionNode.path("methods"); - boolean hasMethods = false; - for (JsonNode methodNode : methodsNode) { - String methodName = methodNode.path("name").asText(); - hasMethods = true; - String thisFunction = methodName + ":" + function; - - authRole.addAllowedFunction(thisFunction); - } - - if (!hasMethods) { - // iterate the list from HTTP_METHODS - for (HTTP_METHODS meth : HTTP_METHODS.values()) { - String thisFunction = meth.toString() + ":" + function; - authRole.addAllowedFunction(thisFunction); - } - } - - } - for (JsonNode userNode : usersNode) { - String username = userNode.path("username").asText().toLowerCase(); - SearchDbAuthUser authUser = null; - if (users.containsKey(username)) { - authUser = users.get(username); - } else { - authUser = new SearchDbAuthUser(); - } - - authUser.setUser(username); - authUser.addRole(roleName, authRole); - users.put(username, authUser); - } - } - } catch (FileNotFoundException fnfe) { - logger.debug("Failed to load the policy file "); - - } catch (ParseException e) { - logger.debug("Failed to Parse the policy file "); - - } catch (JsonProcessingException e) { - logger.debug("JSON processing error while parsing policy file: " + e.getMessage()); - - } catch (IOException e) { - logger.debug("IO Exception while parsing policy file: " + e.getMessage()); - } - - usersInitialized = true; - } - - public static class SearchDbAuthUser { - public SearchDbAuthUser() { - this.roles = new HashMap<>(); - } - - private String username; - private HashMap roles; - - public String getUser() { - return this.username; - } - - public Map getRoles() { - return this.roles; - } - - public void addRole(String roleName, TabularAuthRole authRole) { - this.roles.put(roleName, authRole); - } - - public boolean checkAllowed(String checkFunc) { - for (Map.Entry roleEntry : this.roles.entrySet()) { - TabularAuthRole role = roleEntry.getValue(); - if (role.hasAllowedFunction(checkFunc)) { - return true; - } - } - return false; - } - - public void setUser(String myuser) { - this.username = myuser; - } - } - - public static class TabularAuthRole { - public TabularAuthRole() { - this.allowedFunctions = new ArrayList<>(); - } - - private List allowedFunctions; - - public void addAllowedFunction(String func) { - this.allowedFunctions.add(func); - } - - public void delAllowedFunction(String delFunc) { - if (this.allowedFunctions.contains(delFunc)) { - this.allowedFunctions.remove(delFunc); - } - } - - public boolean hasAllowedFunction(String afunc) { - return this.allowedFunctions.contains(afunc); - } - } - - public static Map getUsers() { - if (!usersInitialized || (users == null)) { - reloadUsers(); - } - return users; - } - - public static boolean authorize(String username, String authFunction) { - if (!usersInitialized || (users == null)) { - init(); - } - if (users.containsKey(username)) { - return users.get(username).checkAllowed(authFunction); - } else { - return false; - } - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java b/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java deleted file mode 100644 index 0b8947e..0000000 --- a/src/main/java/org/onap/aai/sa/rest/AnalysisConfiguration.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; - -/** - * This class encapsulates the configuration of the predefined Analyzer and Filter behaviours that help to tell the - * document store how to index the documents that are provided to it. - */ -public class AnalysisConfiguration { - - /** - * Contains all of the predefined indexing filters. - */ - private FilterSchema[] customFilters; - - /** - * Contains all of the predefined indexing analyzers. - */ - private AnalyzerSchema[] customAnalysers; - - /** - * Indicates whether or not we have imported the filter and analyzer configurations. - */ - private AtomicBoolean configured = new AtomicBoolean(false); - - /** - * A json format string which is readable by Elastic Search and defines all of the custom filters and analyzers that - * we need Elastic Search to know about. - */ - private String esSettings = null; - - private static Logger logger = LoggerFactory.getInstance().getLogger(AnalysisConfiguration.class.getName()); - - - /** - * Imports the filter and analyzer configuration files and builds an Elastic Search readable settings file from the - * contents. - * - * @param filterConfigFile - Location of filter configuration json file - * @param analyzerConfigFile - Location of analyzer configuration json file - */ - public void init(String filterConfigFile, String analyzerConfigFile) { - - if (configured.compareAndSet(false, true)) { - ObjectMapper mapper = new ObjectMapper(); - - File filtersConfig = new File(filterConfigFile); - try { - customFilters = mapper.readValue(filtersConfig, FilterSchema[].class); - } catch (IOException e) { - - // generate log - logger.warn(SearchDbMsgs.FILTERS_CONFIG_FAILURE, filterConfigFile, e.getMessage()); - } - - File analysersConfig = new File(analyzerConfigFile); - try { - customAnalysers = mapper.readValue(analysersConfig, AnalyzerSchema[].class); - } catch (IOException e) { - - // generate log - logger.warn(SearchDbMsgs.ANALYSYS_CONFIG_FAILURE, analyzerConfigFile, e.getMessage()); - } - - esSettings = buildEsIndexSettings(); - } - } - - - /** - * Returns the set of pre-configured filters. - * - * @return - An array of filters. - */ - public FilterSchema[] getFilters() { - return customFilters; - } - - - /** - * Returns the set of pre-configured analyzers. - * - * @return - An array of analyzers. - */ - public AnalyzerSchema[] getAnalyzers() { - init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE); - return customAnalysers; - } - - - /** - * Imports the filter and analyzer configurations and translates those into a settings string that will be parseable - * by Elastic Search. - * - * @return - Elastic Search formatted settings string. - */ - public String getEsIndexSettings() { - - // Generate the es-settings string from our filter and analyzer - // configurations if we have not already done so. - init(SearchDbConstants.SDB_FILTER_CONFIG_FILE, SearchDbConstants.SDB_ANALYSIS_CONFIG_FILE); - - // Now, return the es-settings string. - return esSettings; - } - - - /** - * Constructs a settings string that is readable by Elastic Search based on the contents of the filter and analyzer - * configuration files. - * - * @return Elastic Search formatted settings string. - */ - public String buildEsIndexSettings() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - sb.append("\"analysis\": {"); - - // Define the custom filters. - boolean atLeastOneFilter = false; - sb.append("\"filter\": {"); - AtomicBoolean firstFilter = new AtomicBoolean(true); - for (FilterSchema filter : customFilters) { - - // Append a comma before the next entry, unless it is the - // first one. - if (!firstFilter.compareAndSet(true, false)) { - sb.append(", "); - } - - // Now, build the filter entry. - buildFilterEntry(filter, sb); - atLeastOneFilter = true; - } - sb.append((atLeastOneFilter) ? "}," : "}"); - - // Define the custom analyzers. - sb.append("\"analyzer\": {"); - AtomicBoolean firstAnalyzer = new AtomicBoolean(true); - for (AnalyzerSchema analyzer : customAnalysers) { - - // Prepend a comma before the entry, unless it is the - // first one. - if (!firstAnalyzer.compareAndSet(true, false)) { - sb.append(","); - } - - // Now, construct the entry for this analyzer. - buildAnalyzerEntry(analyzer, sb); - } - sb.append("}"); - - sb.append("}"); - sb.append("}"); - - return sb.toString(); - } - - - /** - * Constructs an ElasticSearch friendly custom filter definition. - * - * @param filter - The filter to generate ElasticSearch json for. - * @param sb - The string builder to append the filter definition to. - */ - private void buildFilterEntry(FilterSchema filter, StringBuilder sb) { - - sb.append("\"" + filter.getName()).append("\": {"); - - sb.append(filter.getConfiguration()); - - sb.append("}"); - } - - - /** - * Constructs an ElasticSearch friendly custom analyzer definition. - * - * @param analyzer - The analyzer to generate ElasticSearch json for. - * @param sb - The string builder to append the analyzer definition to. - */ - private void buildAnalyzerEntry(AnalyzerSchema analyzer, StringBuilder sb) { - - sb.append("\"").append(analyzer.getName()).append("\": {"); - sb.append("\"type\": \"custom\","); - sb.append("\"tokenizer\": ").append("\"").append(analyzer.getTokenizer()).append("\","); - sb.append("\"filter\": ["); - boolean firstFilter = true; - for (String filter : analyzer.getFilters()) { - if (!firstFilter) { - sb.append(","); - } else { - firstFilter = false; - } - sb.append("\"").append(filter).append("\""); - } - sb.append("]"); - sb.append("}"); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java b/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java deleted file mode 100644 index 3971920..0000000 --- a/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import java.util.concurrent.atomic.AtomicBoolean; -import javax.servlet.http.HttpServletRequest; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@Component -@EnableWebSecurity -@RestController -@RequestMapping("/services/search-data-service/v1/analyzers/search") -public class AnalyzerApi { - - private SearchServiceApi searchService = null; - - // Set up the loggers. - private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(IndexApi.class.getName()); - - private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; - - public AnalyzerApi(@Qualifier("searchServiceApi") SearchServiceApi searchService) { - this.searchService = searchService; - } - - @RequestMapping(method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"}) - public ResponseEntity processGet(HttpServletRequest request, @RequestHeader HttpHeaders headers, - ApiUtils apiUtils) { - - HttpStatus responseCode = HttpStatus.INTERNAL_SERVER_ERROR; - String responseString; - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - // Validate that the request is correctly authenticated before going - // any further. - try { - - if (!searchService.validateRequest(headers, request, ApiUtils.Action.GET, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, MSG_AUTHENTICATION_FAILURE); - return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) - .body(MSG_AUTHENTICATION_FAILURE); - } - - } catch (Exception e) { - - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, - "Unexpected authentication failure - cause: " + e.getMessage()); - return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) - .body(MSG_AUTHENTICATION_FAILURE); - } - - - // Now, build the list of analyzers. - try { - responseString = buildAnalyzerList(ElasticSearchHttpController.getInstance().getAnalysisConfig()); - responseCode = HttpStatus.OK; - } catch (Exception e) { - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, - "Unexpected failure retrieving analysis configuration - cause: " + e.getMessage()); - responseString = "Failed to retrieve analysis configuration. Cause: " + e.getMessage(); - } - - // Build the HTTP response. - ResponseEntity response = - ResponseEntity.status(responseCode).contentType(MediaType.APPLICATION_JSON).body(responseString); - - // Generate our audit log. - String unknownLogField = "Unknown"; - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, responseCode.value()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, responseCode.value()), - (request != null) ? request.getMethod() : unknownLogField, - (request != null) ? request.getRequestURL().toString() : unknownLogField, - (request != null) ? request.getRemoteHost() : unknownLogField, - Integer.toString(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } - - /** - * This method takes a list of analyzer objects and generates a simple json structure to enumerate them. - * - *

- * Note, this includes only the aspects of the analyzer object that we want to make public to an external client. - * - * @param analysisConfig - The analysis configuration object to extract the analyzers from. - * @return - A json string enumerating the defined analyzers. - */ - private String buildAnalyzerList(AnalysisConfiguration analysisConfig) { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - AtomicBoolean firstAnalyzer = new AtomicBoolean(true); - for (AnalyzerSchema analyzer : analysisConfig.getAnalyzers()) { - - if (!firstAnalyzer.compareAndSet(true, false)) { - sb.append(", "); - } - - sb.append("{"); - sb.append("\"name\": \"").append(analyzer.getName()).append("\", "); - sb.append("\"description\": \"").append(analyzer.getDescription()).append("\", "); - sb.append("\"behaviours\": ["); - AtomicBoolean firstBehaviour = new AtomicBoolean(true); - for (String behaviour : analyzer.getBehaviours()) { - if (!firstBehaviour.compareAndSet(true, false)) { - sb.append(", "); - } - sb.append("\"").append(behaviour).append("\""); - } - sb.append("]"); - sb.append("}"); - } - sb.append("}"); - - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/ApiUtils.java b/src/main/java/org/onap/aai/sa/rest/ApiUtils.java deleted file mode 100644 index db2fb93..0000000 --- a/src/main/java/org/onap/aai/sa/rest/ApiUtils.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.google.common.base.Strings; -import java.util.UUID; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status.Family; -import org.onap.aai.cl.mdc.MdcContext; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; -import org.slf4j.MDC; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; - -/** - * Spring Imports. - * - */ -public class ApiUtils { - - public static final String URL_PREFIX = "services/search-data-service/v1/search"; - public static final String SEARCH_AUTH_POLICY_NAME = "search"; - - private static final String URI_SEGMENT_INDEXES = "indexes"; - private static final String URI_SEGMENT_DOCUMENTS = "documents"; - - public enum Action { - POST, - GET, - PUT, - DELETE - } - - /** - * This method uses the contents of the supplied HTTP headers and request structures to populate the MDC Context - * used for logging purposes. - * - * @param httpReq - HTTP request structure. - * @param headers - HTTP headers - */ - protected static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { - // Auto generate a transaction if we were not provided one. - String transId = null; - if (headers != null) { - transId = headers.getFirst("X-TransactionId"); - if (Strings.isNullOrEmpty(transId)) { - transId = UUID.randomUUID().toString(); - } - } - - String fromIp = (httpReq != null) ? httpReq.getRemoteHost() : ""; - String fromApp = (headers != null) ? headers.getFirst("X-FromAppId") : ""; - - MdcContext.initialize(transId, SearchDbConstants.SDB_SERVICE_NAME, "", fromApp, fromIp); - } - - protected static void clearMdcContext() { - MDC.clear(); - } - - public static String buildIndexUri(String index) { - return (URL_PREFIX + "/indexes/") + index; - } - - public static String buildDocumentUri(String index, String documentId) { - return buildIndexUri(index) + "/documents/" + documentId; - } - - public static boolean validateIndexUri(String uri) { - uri = uri.startsWith("/") ? uri.substring(1) : uri; - String[] tokens = uri.split("/"); - return (tokens.length == 6) && (tokens[4].equals(URI_SEGMENT_INDEXES)); - } - - public static boolean validateDocumentUri(String uri, boolean requireId) { - uri = uri.startsWith("/") ? uri.substring(1) : uri; - String[] tokens = uri.split("/"); - - if (requireId) { - return (tokens.length == 8) - && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); - } else { - return ((tokens.length == 8) || (tokens.length == 7)) - && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); - } - } - - public static String extractIndexFromUri(String uri) { - uri = uri.startsWith("/") ? uri.substring(1) : uri; - - String[] tokens = uri.split("/"); - - int i = 0; - for (String token : tokens) { - if (token.equals(URI_SEGMENT_INDEXES) && i + 1 < tokens.length) { - return tokens[i + 1]; - } - i++; - } - - return null; - } - - public static String extractIdFromUri(String uri) { - uri = uri.startsWith("/") ? uri.substring(1) : uri; - - String[] tokens = uri.split("/"); - - int i = 0; - for (String token : tokens) { - if (token.equals(URI_SEGMENT_DOCUMENTS) && i + 1 < tokens.length) { - return tokens[i + 1]; - } - i++; - } - - return null; - } - - public static String getHttpStatusString(int httpStatusCode) { - try { - return HttpStatus.valueOf(httpStatusCode).getReasonPhrase(); - } catch (IllegalArgumentException e) { - if (207 == httpStatusCode) { - return "Multi-Status"; - } else { - return "Unknown"; - } - } - } - - public static boolean isSuccessStatusCode(int statusCode) { - return Family.familyOf(statusCode).equals(Family.SUCCESSFUL); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/BulkApi.java b/src/main/java/org/onap/aai/sa/rest/BulkApi.java deleted file mode 100644 index 810f718..0000000 --- a/src/main/java/org/onap/aai/sa/rest/BulkApi.java +++ /dev/null @@ -1,209 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.fge.jsonschema.main.JsonSchema; -import com.github.fge.jsonschema.main.JsonSchemaFactory; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.servlet.http.HttpServletRequest; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; - -/** - * This class encapsulates the REST end points associated with performing bulk operations against the document store. - */ -public class BulkApi { - - /** - * Indicates whether or not we have performed the one-time static initialization required for performing schema - * validation. - */ - protected static AtomicBoolean validationInitialized = new AtomicBoolean(false); - - /** - * Factory used for importing our payload schema for validation purposes. - */ - protected static JsonSchemaFactory schemaFactory = null; - - /** - * Imported payload schema that will be used by our validation methods. - */ - protected static JsonSchema schema = null; - - protected SearchServiceApi searchService = null; - - // Instantiate the loggers. - private static Logger logger = LoggerFactory.getInstance().getLogger(BulkApi.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(BulkApi.class.getName()); - - private static final String MSG_STACK_TRACE = "Stack Trace:\n"; - - /** - * Create a new instance of the BulkApi end point. - */ - public BulkApi(SearchServiceApi searchService) { - this.searchService = searchService; - } - - - /** - * Processes client requests containing a set of operations to be performed in bulk. - * - *

- * Method: POST - * - * @param operations - JSON structure enumerating the operations to be performed. - * @param request - Raw HTTP request. - * @param headers - HTTP headers. - * @return - A standard REST response structure. - */ - public ResponseEntity processPost(String operations, HttpServletRequest request, HttpHeaders headers, - DocumentStoreInterface documentStore) { - ApiUtils.initMdcContext(request, headers); - - if (logger.isDebugEnabled()) { - logger.debug("SEARCH: Process Bulk Request - operations = [" + operations.replaceAll("\n", "") + " ]"); - } - - // We expect a payload containing a JSON structure enumerating the operations to be performed. - if (operations == null) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); - return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Missing payload", request); - } - - try { - // Validate that the request is correctly authenticated before going any further. - if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Authentication failure."); - - return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure.", request); - } - } catch (Exception e) { - // This is a catch all for any unexpected failure trying to perform the authentication. - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, - "Unexpected authentication failure - cause: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug(MSG_STACK_TRACE + e.getStackTrace()); - } - - return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure - cause " + e.getMessage(), - request); - } - - // Marshal the supplied json string into a Java object. - ObjectMapper mapper = new ObjectMapper(); - BulkRequest[] requests = null; - try { - requests = mapper.readValue(operations, BulkRequest[].class); - } catch (IOException e) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Failed to marshal operations list: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug(MSG_STACK_TRACE + e.getStackTrace()); - } - // Populate the result code and entity string for our HTTP response - // and return the response to the client.. - return buildResponse(HttpStatus.BAD_REQUEST.value(), "Unable to marshal operations: " + e.getMessage(), - request); - } - - // Verify that our parsed operations list actually contains some valid operations. - if (requests.length == 0) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Empty operations list in bulk request"); - - // Populate the result code and entity string for our HTTP response - // and return the response to the client.. - return buildResponse(HttpStatus.BAD_REQUEST.value(), "Empty operations list in bulk request", request); - } - - int resultCode; - String resultString; - - try { - // Now, forward the set of bulk operations to the DAO for processing. - OperationResult result = documentStore.performBulkOperations(requests); - - resultCode = result.getResultCode(); - resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - } catch (DocumentStoreOperationException e) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, - "Unexpected failure communicating with document store: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug(MSG_STACK_TRACE + e.getStackTrace()); - } - - resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); - resultString = "Unexpected failure processing bulk operations: " + e.getMessage(); - } - - ResponseEntity response = - ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); - - if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { - logger.info(SearchDbMsgs.PROCESSED_BULK_OPERATIONS); - } else { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, response.getBody()); - } - - return buildResponse(resultCode, resultString, request); - } - - /** - * This method generates an audit log and returns an HTTP response object. - * - * @param resultCode - The result code to report. - * @param resultString - The result string to report. - * @param request - The HTTP request to extract data from for the audit log. - * @return - An HTTP response object. - */ - private ResponseEntity buildResponse(int resultCode, String resultString, HttpServletRequest request) { - ResponseEntity response = - ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); - - // Generate our audit log. - String unknownLogField = "Unknown"; - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, ApiUtils.getHttpStatusString(resultCode)), - (request != null) ? request.getMethod() : unknownLogField, - (request != null) ? request.getRequestURL().toString() : unknownLogField, - (request != null) ? request.getRemoteHost() : unknownLogField, - Integer.toString(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java b/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java deleted file mode 100644 index 7c096a6..0000000 --- a/src/main/java/org/onap/aai/sa/rest/BulkMetaData.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -public class BulkMetaData { - - private String url; - private String etag; - - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getEtag() { - return etag; - } - - public void setEtag(String anEtag) { - this.etag = anEtag; - } - - @Override - public String toString() { - return "MetaData: [url=" + url + ", etag=" + etag + "]"; - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/BulkOperation.java b/src/main/java/org/onap/aai/sa/rest/BulkOperation.java deleted file mode 100644 index 1490f97..0000000 --- a/src/main/java/org/onap/aai/sa/rest/BulkOperation.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -/** - * This class represents a single instance of an operation to be performed as part of a bulk request. - */ -public class BulkOperation { - - /** - * Contains meta data to be passed to the document store for it to perform the operation. - */ - private BulkMetaData metaData; - - /** - * Contains the contents of the document to be acted on. - */ - private Document document; - - - public void setMetaData(BulkMetaData metaData) { - this.metaData = metaData; - } - - public BulkMetaData getMetaData() { - return metaData; - } - - public Document getDocument() { - return document; - } - - public void setDocument(Document document) { - this.document = document; - } - - @Override - public String toString() { - return "Operation: [" + metaData.toString() + ", " + document + "]"; - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/BulkRequest.java b/src/main/java/org/onap/aai/sa/rest/BulkRequest.java deleted file mode 100644 index 1f8b50e..0000000 --- a/src/main/java/org/onap/aai/sa/rest/BulkRequest.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - - -/** - * This class represents a single instance of a request from the search client that would be part of a bundle of such - * operations sent in a single bulk request. - */ -public class BulkRequest { - - public enum OperationType { - CREATE, - UPDATE, - DELETE - } - - private BulkOperation create; - private BulkOperation update; - private BulkOperation delete; - - public BulkOperation getCreate() { - return create; - } - - public void setCreate(BulkOperation create) { - this.create = create; - } - - public BulkOperation getUpdate() { - return update; - } - - public void setUpdate(BulkOperation update) { - this.update = update; - } - - public BulkOperation getDelete() { - return delete; - } - - public void setDelete(BulkOperation delete) { - this.delete = delete; - } - - public OperationType getOperationType() { - - if (create != null) { - return OperationType.CREATE; - } else if (update != null) { - return OperationType.UPDATE; - } else if (delete != null) { - return OperationType.DELETE; - } else { - return null; - } - } - - public BulkOperation getOperation() { - if (create != null) { - return create; - } else if (update != null) { - return update; - } else if (delete != null) { - return delete; - } else { - return null; - } - } - - public String getIndex() { - return ApiUtils.extractIndexFromUri(getOperation().getMetaData().getUrl()); - } - - public String getId() { - return ApiUtils.extractIdFromUri(getOperation().getMetaData().getUrl()); - } - - @Override - public String toString() { - - if (create != null) { - return "create: [" + create.toString() + "]\n"; - } else if (update != null) { - return "update: [" + update.toString() + "]\n"; - } else if (delete != null) { - return "delete: [" + delete.toString() + "]\n"; - } else { - return "UNDEFINED"; - } - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/Document.java b/src/main/java/org/onap/aai/sa/rest/Document.java deleted file mode 100644 index e9bcaf4..0000000 --- a/src/main/java/org/onap/aai/sa/rest/Document.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -public class Document { - private Map fields = new HashMap<>(); - - @JsonAnyGetter - public Map getFields() { - return fields; - } - - @JsonAnySetter - public void setField(String name, Object value) { - fields.put(name, value); - } - - public String toJson() throws JsonProcessingException { - return new ObjectMapper().writeValueAsString(this); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("Document: ["); - for (Entry entry : fields.entrySet()) { - sb.append(entry.getKey()).append(": ").append(entry.getValue()); - } - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/DocumentApi.java b/src/main/java/org/onap/aai/sa/rest/DocumentApi.java deleted file mode 100644 index da8be98..0000000 --- a/src/main/java/org/onap/aai/sa/rest/DocumentApi.java +++ /dev/null @@ -1,599 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntityImpl; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; -import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.onap.aai.sa.searchdbabstraction.searchapi.SearchStatement; -import org.onap.aai.sa.searchdbabstraction.searchapi.SuggestionStatement; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; - -public class DocumentApi { - private static final String MSG_REQUEST_BODY = "Request Body: "; - private static final String REQUEST_HEADER_RESOURCE_VERSION = "If-Match"; - private static final String RESPONSE_HEADER_RESOURCE_VERSION = "ETag"; - private static final String REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION = "X-CreateIndex"; - - protected SearchServiceApi searchService = null; - - private Logger logger = LoggerFactory.getInstance().getLogger(DocumentApi.class.getName()); - private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(DocumentApi.class.getName()); - - public DocumentApi(SearchServiceApi searchService) { - this.searchService = searchService; - } - - public ResponseEntity processPost(String content, HttpServletRequest request, HttpHeaders headers, - HttpServletResponse httpResponse, String index, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - if (content == null) { - return handleError(request, content, HttpStatus.BAD_REQUEST); - } - - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processPost", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); - document.setContent(content); - - DocumentOperationResult result = - documentStore.createDocument(index, document, implicitlyCreateIndex(headers)); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - - if (httpResponse != null) { - httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); - } - ResponseEntity response = - ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); - logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); - logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - public ResponseEntity processPut(String content, HttpServletRequest request, HttpHeaders headers, - HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - if (content == null) { - return handleError(request, content, HttpStatus.BAD_REQUEST); - } - - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.PUT, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processPut", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); - - DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); - document.setId(id); - document.setContent(content); - document.setVersion(resourceVersion); - - DocumentOperationResult result = null; - if (resourceVersion == null) { - result = documentStore.createDocument(index, document, implicitlyCreateIndex(headers)); - } else { - result = documentStore.updateDocument(index, document, implicitlyCreateIndex(headers)); - } - - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - if (httpResponse != null) { - httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); - } - ResponseEntity response = - ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); - logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - public ResponseEntity processDelete(String content, HttpServletRequest request, HttpHeaders headers, - HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.DELETE, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processDelete", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); - if (resourceVersion == null || resourceVersion.isEmpty()) { - return handleError(request, "Request header 'If-Match' missing", HttpStatus.BAD_REQUEST); - } - - DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); - document.setId(id); - document.setVersion(resourceVersion); - - DocumentOperationResult result = documentStore.deleteDocument(index, document); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - - if (httpResponse != null) { - httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); - } - ResponseEntity response; - if (output == null) { - response = ResponseEntity.status(result.getResultCode()).build(); - } else { - response = ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) - .body(output); - } - - logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - public ResponseEntity processGet(String content, HttpServletRequest request, HttpHeaders headers, - HttpServletResponse httpResponse, String index, String id, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.GET, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "DocumentApi.processGet", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - String resourceVersion = headers.getFirst(REQUEST_HEADER_RESOURCE_VERSION); - - DocumentStoreDataEntityImpl document = new DocumentStoreDataEntityImpl(); - document.setId(id); - document.setVersion(resourceVersion); - - DocumentOperationResult result = documentStore.getDocument(index, document); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - if (httpResponse != null) { - httpResponse.setHeader(RESPONSE_HEADER_RESOURCE_VERSION, result.getResultVersion()); - } - ResponseEntity response = - ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); - logResult(request, HttpStatus.valueOf(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - public ResponseEntity processSearchWithGet(String content, HttpServletRequest request, HttpHeaders headers, - String index, String queryText, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.GET, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processSearchWithGet", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - SearchOperationResult result = documentStore.search(index, queryText); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSearchResult()); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - ResponseEntity response = - ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - public ResponseEntity queryWithGetWithPayload(String content, HttpServletRequest request, - HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "GET", - (request != null) ? request.getRequestURL().toString() : ""); - if (logger.isDebugEnabled()) { - logger.debug(MSG_REQUEST_BODY + content); - } - return processQuery(index, content, request, headers, documentStore); - } - - public ResponseEntity processSearchWithPost(String content, HttpServletRequest request, HttpHeaders headers, - String index, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", - (request != null) ? request.getRequestURL().toString() : ""); - if (logger.isDebugEnabled()) { - logger.debug(MSG_REQUEST_BODY + content); - } - - return processQuery(index, content, request, headers, documentStore); - } - - - public ResponseEntity processSuggestQueryWithPost(String content, HttpServletRequest request, - HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", - (request != null) ? request.getRequestURL().toString() : ""); - if (logger.isDebugEnabled()) { - logger.debug(MSG_REQUEST_BODY + content); - } - - return processSuggestQuery(index, content, request, headers, documentStore); - } - - /** - * Common handler for query requests. This is called by both the GET with payload and POST with payload variants of - * the query endpoint. - * - * @param index - The index to be queried against. - * @param content - The payload containing the query structure. - * @param request - The HTTP request. - * @param headers - The HTTP headers. - * @return - A standard HTTP response. - */ - private ResponseEntity processQuery(String index, String content, HttpServletRequest request, - HttpHeaders headers, DocumentStoreInterface documentStore) { - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - - // Make sure that we were supplied a payload before proceeding. - if (content == null) { - return handleError(request, content, HttpStatus.BAD_REQUEST); - } - - // Validate that the request has the appropriate authorization. - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processQuery", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - SearchStatement searchStatement; - - try { - // Marshall the supplied request payload into a search statement - // object. - searchStatement = mapper.readValue(content, SearchStatement.class); - - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.BAD_REQUEST); - } - - // Now, submit the search statement, translated into - // ElasticSearch syntax, to the document store DAO. - SearchOperationResult result = documentStore.searchWithPayload(index, searchStatement.toElasticSearch()); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = prepareOutput(mapper, result); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - ResponseEntity response = - ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON).body(output); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - - /** - * Common handler for query requests. This is called by both the GET with payload and POST with payload variants of - * the query endpoint. - * - * @param index - The index to be queried against. - * @param content - The payload containing the query structure. - * @param request - The HTTP request. - * @param headers - The HTTP headers. - * @return - A standard HTTP response. - */ - private ResponseEntity processSuggestQuery(String index, String content, HttpServletRequest request, - HttpHeaders headers, DocumentStoreInterface documentStore) { - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - - // Make sure that we were supplied a payload before proceeding. - if (content == null) { - return handleError(request, content, HttpStatus.BAD_REQUEST); - } - - // Validate that the request has the appropriate authorization. - boolean isValid; - try { - isValid = searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME); - - } catch (Exception e) { - logger.info(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "processQuery", e.getMessage()); - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - if (!isValid) { - return handleError(request, content, HttpStatus.FORBIDDEN); - } - - SuggestionStatement suggestionStatement; - - try { - // Marshall the supplied request payload into a search statement - // object. - suggestionStatement = mapper.readValue(content, SuggestionStatement.class); - - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.BAD_REQUEST); - } - - // Now, submit the search statement, translated into - // ElasticSearch syntax, to the document store DAO. - SearchOperationResult result = - documentStore.suggestionQueryWithPayload(index, suggestionStatement.toElasticSearch()); - String output = null; - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - output = prepareSuggestOutput(mapper, result); - } else { - output = result.getError() != null - ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) - : result.getFailureCause(); - } - ResponseEntity response = ResponseEntity.status(result.getResultCode()).body(output); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - - } catch (Exception e) { - return handleError(request, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - /** - * Checks the supplied HTTP headers to see if we should allow the underlying document store to implicitly create the - * index referenced in a document PUT or POST if it does not already exist in the data store. - * - * @param headers - The HTTP headers to examine. - * - * @return - true if the headers indicate that missing indices should be implicitly created, false otherwise. - */ - private boolean implicitlyCreateIndex(HttpHeaders headers) { - String implicitIndexCreationHeader = headers.getFirst(REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION); - return implicitIndexCreationHeader != null && "true".equals(implicitIndexCreationHeader); - } - - private String prepareOutput(ObjectMapper mapper, SearchOperationResult result) throws JsonProcessingException { - StringBuffer output = new StringBuffer(); - output.append("{\r\n\"searchResult\":"); - output.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSearchResult())); - AggregationResults aggs = result.getAggregationResult(); - if (aggs != null) { - output.append(",\r\n\"aggregationResult\":"); - output.append(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() - .writeValueAsString(aggs)); - } - output.append("\r\n}"); - return output.toString(); - } - - private String prepareSuggestOutput(ObjectMapper mapper, SearchOperationResult result) - throws JsonProcessingException { - StringBuffer output = new StringBuffer(); - output.append("{\r\n\"searchResult\":"); - output.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSuggestResult())); - AggregationResults aggs = result.getAggregationResult(); - if (aggs != null) { - output.append(",\r\n\"aggregationResult\":"); - output.append(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() - .writeValueAsString(aggs)); - } - output.append("\r\n}"); - return output.toString(); - } - - private ResponseEntity handleError(HttpServletRequest request, String message, HttpStatus status) { - logResult(request, status); - return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(message); - } - - void logResult(HttpServletRequest request, HttpStatus status) { - - logger.info(SearchDbMsgs.PROCESS_REST_REQUEST, (request != null) ? request.getMethod() : "", - (request != null) ? request.getRequestURL().toString() : "", - (request != null) ? request.getRemoteHost() : "", Integer.toString(status.value())); - - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status.value()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), - (request != null) ? request.getMethod() : "", - (request != null) ? request.getRequestURL().toString() : "", - (request != null) ? request.getRemoteHost() : "", Integer.toString(status.value())); - - // Clear the MDC context so that no other transaction inadvertently uses our transaction id. - ApiUtils.clearMdcContext(); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/IndexApi.java b/src/main/java/org/onap/aai/sa/rest/IndexApi.java deleted file mode 100644 index 04fbcf3..0000000 --- a/src/main/java/org/onap/aai/sa/rest/IndexApi.java +++ /dev/null @@ -1,402 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.FileNotFoundException; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; - -/** - * This class encapsulates the REST end points associated with manipulating indexes in the document store. - */ -public class IndexApi { - - private static final String UNKNOWN_LOG_FIELD_STR = "Unknown"; - private static final String MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE = - "Unexpected authentication failure - cause: "; - private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; - private static final String HEADER_VALIDATION_SUCCESS = "SUCCESS"; - protected SearchServiceApi searchService = null; - - /** - * Configuration for the custom analyzers that will be used for indexing. - */ - protected AnalysisConfiguration analysisConfig; - - // Set up the loggers. - private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(IndexApi.class.getName()); - - - public IndexApi(SearchServiceApi searchService) { - this.searchService = searchService; - init(); - } - - - /** - * Initializes the end point. - * - * @throws FileNotFoundException - * @throws IOException - * @throws DocumentStoreOperationException - */ - public void init() { - - // Instantiate our analysis configuration object. - analysisConfig = new AnalysisConfiguration(); - } - - - /** - * Processes client requests to create a new index and document type in the document store. - * - * @param documentSchema - The contents of the request body which is expected to be a JSON structure which - * corresponds to the schema defined in document.schema.json - * @param index - The name of the index to create. - * @return - A Standard REST response - */ - public ResponseEntity processCreateIndex(String documentSchema, HttpServletRequest request, - HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - - int resultCode = 500; - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - // Validate that the request is correctly authenticated before going any further. - try { - if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - - } catch (Exception e) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, - MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - - - // We expect a payload containing the document schema. Make sure - // it is present. - if (documentSchema == null) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Missing document schema payload"); - return errorResponse(HttpStatus.valueOf(resultCode), "Missing payload", request); - } - - String resultString; - - try { - // Marshal the supplied json string into a document schema object. - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); - - // Now, ask the DAO to create the index. - OperationResult result = documentStore.createIndex(index, schema); - - // Extract the result code and string from the OperationResult - // object so that we can use them to generate a standard REST - // response. - // Note that we want to return a 201 result code on a successful - // create, so if we get back a 200 from the document store, - // translate that int a 201. - resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); - resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - - } catch (com.fasterxml.jackson.core.JsonParseException - | com.fasterxml.jackson.databind.JsonMappingException e) { - - // We were unable to marshal the supplied json string into a valid - // document schema, so return an appropriate error response. - resultCode = HttpStatus.BAD_REQUEST.value(); - resultString = "Malformed schema: " + e.getMessage(); - - } catch (IOException e) { - - // We'll treat this is a general internal error. - resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); - resultString = "IO Failure: " + e.getMessage(); - } - - ResponseEntity response = - ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); - - if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { - logger.info(SearchDbMsgs.CREATED_INDEX, index); - } else { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, resultString); - } - - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode).setField( - LogLine.DefinedFields.RESPONSE_DESCRIPTION, HttpStatus.valueOf(resultCode).toString()), - (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, - Integer.toString(response.getStatusCodeValue())); - - - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - // Finally, return the response. - return response; - } - - /** - * This function accepts any JSON and will "blindly" write it to the document store. - * - * Note, eventually this "dynamic" flow should follow the same JSON-Schema validation procedure as the normal create - * index flow. - * - * @param dynamicSchema - The JSON string that will be sent to the document store. - * @param index - The name of the index to be created. - * @param documentStore - The document store specific interface. - * @return The result of the document store interface's operation. - */ - public ResponseEntity processCreateDynamicIndex(String dynamicSchema, HttpServletRequest request, - HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - - ResponseEntity response = null; - - ResponseEntity validationResponse = - validateRequest(request, headers, index, SearchDbMsgs.INDEX_CREATE_FAILURE); - - - if (validationResponse.getStatusCodeValue() != HttpStatus.OK.value()) { - response = validationResponse; - } else { - OperationResult result = documentStore.createDynamicIndex(index, dynamicSchema); - - int resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); - String resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - - response = ResponseEntity.status(resultCode).body(resultString); - } - - return response; - } - - /** - * Processes a client request to remove an index from the document store. Note that this implicitly deletes all - * documents contained within that index. - * - * @param index - The index to be deleted. - * @return - A standard REST response. - */ - public ResponseEntity processDelete(String index, HttpServletRequest request, HttpHeaders headers, - DocumentStoreInterface documentStore) { - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - ResponseEntity response; - - // Validate that the request is correctly authenticated before going - // any further. - try { - if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - - } catch (Exception e) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, - MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - - try { - // Send the request to the document store. - response = responseFromOperationResult(documentStore.deleteIndex(index)); - } catch (DocumentStoreOperationException e) { - response = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON) - .body(e.getMessage()); - } - - if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { - logger.info(SearchDbMsgs.DELETED_INDEX, index); - } else { - logger.warn(SearchDbMsgs.INDEX_DELETE_FAILURE, index, response.getBody()); - } - - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatusCodeValue()).setField( - LogLine.DefinedFields.RESPONSE_DESCRIPTION, response.getStatusCode().getReasonPhrase()), - (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, - Integer.toString(response.getStatusCodeValue())); - - // Clear the MDC context so that no other transaction inadvertently uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } - - - /** - * This method takes a JSON format document schema and produces a set of field mappings in the form that Elastic - * Search expects. - * - * @param documentSchema - A document schema expressed as a JSON string. - * @return - A JSON string expressing an Elastic Search mapping configuration. - * @throws com.fasterxml.jackson.core.JsonParseException - * @throws com.fasterxml.jackson.databind.JsonMappingException - * @throws IOException - */ - public String generateDocumentMappings(String documentSchema) throws IOException { - - // Unmarshal the json content into a document schema object. - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); - - // Now, generate the Elastic Search mapping json and return it. - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"properties\": {"); - - boolean first = true; - for (DocumentFieldSchema field : schema.getFields()) { - - if (!first) { - sb.append(","); - } else { - first = false; - } - - sb.append("\"").append(field.getName()).append("\": {"); - - // The field type is mandatory. - sb.append("\"type\": \"").append(field.getDataType()).append("\""); - - // If the index field was specified, then append it. - if (field.getSearchable() != null) { - sb.append(", \"index\": \"").append(field.getSearchable() ? "analyzed" : "not_analyzed").append("\""); - } - - // If a search analyzer was specified, then append it. - if (field.getSearchAnalyzer() != null) { - sb.append(", \"search_analyzer\": \"").append(field.getSearchAnalyzer()).append("\""); - } - - // If an indexing analyzer was specified, then append it. - if (field.getIndexAnalyzer() != null) { - sb.append(", \"analyzer\": \"").append(field.getIndexAnalyzer()).append("\""); - } else { - sb.append(", \"analyzer\": \"").append("whitespace").append("\""); - } - - sb.append("}"); - } - - sb.append("}"); - sb.append("}"); - - logger.debug("Generated document mappings: " + sb.toString()); - - return sb.toString(); - } - - - /** - * Converts an {@link OperationResult} to a standard REST {@link ResponseEntity} object. - * - * @param result - The {@link OperationResult} to be converted. - * @return - The equivalent {@link ResponseEntity} object. - */ - public ResponseEntity responseFromOperationResult(OperationResult result) { - - if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { - return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) - .body(result.getResult()); - } else { - if (result.getFailureCause() != null) { - return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) - .body(result.getFailureCause()); - } else { - return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) - .body(result.getResult()); - } - } - } - - public ResponseEntity errorResponse(HttpStatus status, String msg, HttpServletRequest request) { - - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status.value()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), - (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, - (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, Integer.toString(status.value())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(msg); - } - - - /** - * A helper method used for validating/authenticating an incoming request. - * - * @param request - The http request that will be validated. - * @param headers - The http headers that will be validated. - * @param index - The name of the index that the document store request is being made against. - * @param failureMsgEnum - The logging message to be used upon validation failure. - * @return A success or failure response - */ - private ResponseEntity validateRequest(HttpServletRequest request, HttpHeaders headers, String index, - SearchDbMsgs failureMsgEnum) { - try { - if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(failureMsgEnum, index, MSG_AUTHENTICATION_FAILURE); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - } catch (Exception e) { - logger.warn(failureMsgEnum, index, MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); - } - return ResponseEntity.status(HttpStatus.OK).body(HEADER_VALIDATION_SUCCESS); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java b/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java deleted file mode 100644 index d62bfd6..0000000 --- a/src/main/java/org/onap/aai/sa/rest/SearchServiceApi.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import java.security.cert.X509Certificate; -import javax.security.auth.x500.X500Principal; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.onap.aai.sa.auth.SearchDbServiceAuth; -import org.onap.aai.sa.rest.ApiUtils.Action; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@Component -@EnableWebSecurity -@RestController -@RequestMapping("/services/search-data-service/v1/search") -public class SearchServiceApi { - - /** - * The Data Access Object that we will use to interact with the document store. - */ - protected DocumentStoreInterface documentStore = null; - protected ApiUtils apiUtils = null; - - /** - * Create a new instance of the end point. - */ - public SearchServiceApi() { - - // Perform one-time initialization. - init(); - } - - - /** - * Performs all one-time initialization required for the end point. - */ - public void init() { - // Instantiate our Document Store DAO. - documentStore = ElasticSearchHttpController.getInstance(); - } - - @RequestMapping(value = "/indexes/{index}", method = RequestMethod.PUT, produces = {"application/json"}) - public ResponseEntity processCreateIndex(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - // Forward the request to our index API to create the index. - IndexApi indexApi = new IndexApi(this); - return indexApi.processCreateIndex(requestBody, request, headers, index, documentStore); - } - - @RequestMapping(value = "/indexes/{index}", method = RequestMethod.DELETE, consumes = {"application/json"}, - produces = {"application/json"}) - public ResponseEntity processDeleteIndex(HttpServletRequest request, @RequestHeader HttpHeaders headers, - @PathVariable("index") String index) { - - // Forward the request to our index API to delete the index. - IndexApi indexApi = new IndexApi(this); - return indexApi.processDelete(index, request, headers, documentStore); - } - - - @RequestMapping(value = "/indexes/{index}/documents", method = RequestMethod.POST, consumes = {"application/json"}) - public ResponseEntity processCreateDocWithoutId(@RequestBody String requestBody, HttpServletRequest request, - HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - // Forward the request to our document API to create the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processPost(requestBody, request, headers, httpResponse, index, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.PUT, - consumes = {"application/json"}) - public ResponseEntity processUpsertDoc(@RequestBody String requestBody, HttpServletRequest request, - HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index, - @PathVariable("id") String id) { - - // Forward the request to our document API to upsert the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processPut(requestBody, request, headers, httpResponse, index, id, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.GET) - public ResponseEntity processGetDocument(HttpServletRequest request, HttpServletResponse httpResponse, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { - - // Forward the request to our document API to retrieve the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processGet("", request, headers, httpResponse, index, id, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.DELETE, - consumes = {"application/json"}) - public ResponseEntity processDeleteDoc(HttpServletRequest request, HttpServletResponse httpResponse, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { - - // Forward the request to our document API to delete the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processDelete("", request, headers, httpResponse, index, id, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/query/{queryText}", method = RequestMethod.GET) - public ResponseEntity processInlineQuery(HttpServletRequest request, @RequestHeader HttpHeaders headers, - @PathVariable("index") String index, @PathVariable("queryText") String queryText) { - - // Forward the request to our document API to delete the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processSearchWithGet("", request, headers, index, queryText, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.GET, consumes = {"application/json"}) - public ResponseEntity processQueryWithGet(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - // Forward the request to our document API to delete the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.queryWithGetWithPayload(requestBody, request, headers, index, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.POST, consumes = {"application/json"}) - public ResponseEntity processQuery(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - // Forward the request to our document API to delete the document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processSearchWithPost(requestBody, request, headers, index, documentStore); - } - - @RequestMapping(value = "/indexes/{index}/suggest", method = RequestMethod.POST, consumes = {"application/json"}) - public ResponseEntity processSuggestQuery(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - // Forward the request to our document API to query suggestions in the - // document. - DocumentApi documentApi = new DocumentApi(this); - return documentApi.processSuggestQueryWithPost(requestBody, request, headers, index, documentStore); - } - - @RequestMapping(value = "/indexes/dynamic/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) - public ResponseEntity processCreateDynamicIndex(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - // Forward the request to our index API to create the index. - IndexApi indexApi = new IndexApi(this); - return indexApi.processCreateDynamicIndex(requestBody, request, headers, index, documentStore); - } - - @RequestMapping(value = "/bulk", method = RequestMethod.POST, consumes = {"application/json"}, - produces = {"application/json"}) - public ResponseEntity processBulkRequest(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers) { - - // Forward the request to our document API to delete the document. - BulkApi bulkApi = new BulkApi(this); - return bulkApi.processPost(requestBody, request, headers, documentStore); - } - - protected boolean validateRequest(HttpHeaders headers, HttpServletRequest req, Action action, - String authPolicyFunctionName) { - - boolean isUserAuthEnabled = ((ElasticSearchHttpController)documentStore).getElasticSearchConfig().useAuthorizationUser(); - if(! isUserAuthEnabled) { - return true; - } - - SearchDbServiceAuth serviceAuth = new SearchDbServiceAuth(); - - String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); - String authUser = null; - if (cipherSuite != null) { - Object x509CertAttribute = req.getAttribute("javax.servlet.request.X509Certificate"); - if (x509CertAttribute != null) { - X509Certificate[] certChain = (X509Certificate[]) x509CertAttribute; - X509Certificate clientCert = certChain[0]; - X500Principal subjectDn = clientCert.getSubjectX500Principal(); - authUser = subjectDn.toString(); - } - } - - if (authUser == null) { - return false; - } - - String status = - serviceAuth.authUser(headers, authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); - return status.equals("OK"); - } -} diff --git a/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java b/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java deleted file mode 100644 index 74e46f4..0000000 --- a/src/main/java/org/onap/aai/sa/rest/SettingConfiguration.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2019 AT&T Intellectual Property. All rights reserved. - * Copyright © 2019 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========================================================= - */ -package org.onap.aai.sa.rest; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.concurrent.atomic.AtomicBoolean; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; - - -public class SettingConfiguration { - - /** - * Indicates whether or not we have imported the filter and analyzer configurations. - */ - private AtomicBoolean configured = new AtomicBoolean(false); - - /** - * A json format string which is readable by Elastic Search and defines all of the custom filters and analyzers that - * we need Elastic Search to know about. - */ - private String settings; - - public void init(String settingConfigFile) { - - if (configured.compareAndSet(false, true)) { - try { - Path path = Paths.get(settingConfigFile); - settings = new String(Files.readAllBytes(path)); - - // Remove the enclosing brackets from the json blob. - settings = settings.replaceFirst("\\{", ""); - settings = settings.substring(0, settings.lastIndexOf("}")); - } catch (IOException e) { - // It is valid not to have a settings file. - settings = ""; - } - } - } - - - /** - * Returns the set of pre-configured settings. - * - * @return - settings. - */ - public String getSettings() { - init(SearchDbConstants.SDB_SETTINGS_CONFIG_FILE); - return settings; - } - - public String getSettingsWithAnalysis(AnalysisConfiguration analysisConfig) { - String ac = analysisConfig.getEsIndexSettings(); - StringBuilder sb = new StringBuilder(); - sb.append(ac.substring(0, ac.lastIndexOf("}"))); - - if (!getSettings().trim().isEmpty()) { - sb.append(", " + getSettings()); - } - - sb.append(" }"); - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java deleted file mode 100644 index 96929c7..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/RestEchoService.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ - -package org.onap.aai.sa.searchdbabstraction; - -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -/** - * Exposes REST endpoints for a simple echo service. - */ -@RestController -@RequestMapping("/services/search-data-service/v1") -public class RestEchoService { - - /** - * REST endpoint for a simple echo service. - * - * @param input - The value to be echoed back. - * @return - The input value. - */ - @RequestMapping(value = "/echo/{input}", method = {RequestMethod.GET}) - public String ping(@PathVariable("input") String input) { - return "[Search Database Abstraction Micro Service] - Echo Service: " + input + "."; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java deleted file mode 100644 index 4680ded..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfig.java +++ /dev/null @@ -1,240 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.config; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Optional; -import java.util.Properties; - -import org.apache.commons.lang.StringUtils; -import org.eclipse.jetty.util.security.Password; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; - -public class ElasticSearchConfig { - - private String uriScheme; - private String trustStore; - private String trustStorePassword; - private String keyStore; - private String keyStorePassword; - private String authUser; - private String authPassword; - private String ipAddress; - private String httpPort; - private String javaApiPort; - private String clusterName; - private String authorizationEnabled; - - public static final String ES_CLUSTER_NAME = "es.cluster-name"; - public static final String ES_IP_ADDRESS = "es.ip-address"; - public static final String ES_HTTP_PORT = "es.http-port"; - public static final String ES_URI_SCHEME = "es.uri-scheme"; - public static final String ES_TRUST_STORE = "es.trust-store"; - public static final String ES_TRUST_STORE_ENC = "es.trust-store-password"; - public static final String ES_KEY_STORE = "es.key-store"; - public static final String ES_KEY_STORE_ENC = "es.key-store-password"; - public static final String ES_AUTH_USER = "es.auth-user"; - public static final String ES_AUTH_ENC = "es.auth-password"; - public static final String ES_AUTH_ENABLED = "es.auth.authorization.enabled"; - - private static final String DEFAULT_URI_SCHEME = "http"; - private static final String JAVA_API_PORT_DEFAULT = "9300"; - private String authValue; - - public ElasticSearchConfig(Properties props) { - setUriScheme(props.getProperty(ES_URI_SCHEME)); - if (getUriScheme().equals("https")) { - initializeHttpsProperties(props); - } - setClusterName(props.getProperty(ES_CLUSTER_NAME)); - setIpAddress(props.getProperty(ES_IP_ADDRESS)); - setHttpPort(props.getProperty(ES_HTTP_PORT)); - setJavaApiPort(JAVA_API_PORT_DEFAULT); - initializeAuthValues(props); - setAuthorizationEnabled(props.getProperty(ES_AUTH_ENABLED)); - } - - - public String getUriScheme() { - return this.uriScheme; - } - - public String getIpAddress() { - return ipAddress; - } - - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - public String getHttpPort() { - return httpPort; - } - - public void setHttpPort(String httpPort) { - this.httpPort = httpPort; - } - - public String getJavaApiPort() { - return javaApiPort; - } - - public void setJavaApiPort(String javaApiPort) { - this.javaApiPort = javaApiPort; - } - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public void setKeyStore(String keyStore) { - this.keyStore = keyStore; - } - - public void setKeyStorePassword(String keyStorePassword) { - this.keyStorePassword = keyStorePassword; - } - - public String getKeyStorePath() { - return keyStore; - } - - public String getKeyStorePassword() { - return keyStorePassword; - } - - public String getTrustStorePath() { - return trustStore; - } - - public void setTrustStore(String trustStore) { - this.trustStore = trustStore; - } - - public void setTrustStorePassword(String trustStorePassword) { - this.trustStorePassword = trustStorePassword; - } - - public String getTrustStorePassword() { - return trustStorePassword; - } - - public void setAuthUser(String authUser) { - this.authUser = authUser; - } - - public String getAuthUser() { - return authUser; - } - - public void setAuthPassword(String authPassword) { - this.authPassword = authPassword; - } - - public String getAuthPassword() { - return authPassword; - } - - public boolean useAuth() { - return getAuthUser() != null || getAuthPassword() != null; - } - - public String getAuthValue() { - return authValue; - } - - public String getAuthorizationEnabled() { - return authorizationEnabled; - } - - public void setAuthorizationEnabled(String authorizationEnabled) { - this.authorizationEnabled = authorizationEnabled; - } - - public boolean useAuthorizationUser() { - return getAuthorizationEnabled()== null? true : Boolean.parseBoolean(getAuthorizationEnabled()); - } - - @Override - public String toString() { - return String.format( - "%s://%s:%s (cluster=%s) (API port=%s)%nauth=%s%ntrustStore=%s (passwd %s)%nkeyStore=%s (passwd %s)%nauthorizationUser=%s", - uriScheme, ipAddress, httpPort, clusterName, javaApiPort, useAuth(), trustStore, - trustStorePassword != null, keyStore, keyStorePassword != null, useAuthorizationUser()); - } - - private void initializeAuthValues(Properties props) { - setAuthUser(props.getProperty(ES_AUTH_USER)); - Optional passwordValue = Optional.ofNullable(props.getProperty(ES_AUTH_ENC)); - if (passwordValue.isPresent()) { - setAuthPassword(Password.deobfuscate(passwordValue.get())); - } - if (useAuth()) { - authValue = "Basic " + Base64.getEncoder() - .encodeToString((getAuthUser() + ":" + getAuthPassword()).getBytes(StandardCharsets.UTF_8)); - } - } - - private void initializeHttpsProperties(Properties props) { - Optional trustStoreFile = Optional.ofNullable(props.getProperty(ES_TRUST_STORE)); - if (trustStoreFile.isPresent()) { - setTrustStore(SearchDbConstants.SDB_SPECIFIC_CONFIG + trustStoreFile.get()); - } - - Optional passwordValue = Optional.ofNullable(props.getProperty(ES_TRUST_STORE_ENC)); - if (passwordValue.isPresent()) { - if(passwordValue.get().startsWith("OBF:")){ - setTrustStorePassword(Password.deobfuscate(passwordValue.get())); - }else if(passwordValue.get().startsWith("ENV:")){ - setTrustStorePassword(System.getenv(StringUtils.removeStart(passwordValue.get(), "ENV:"))); - } - else{ - setTrustStorePassword(passwordValue.get()); - } - } - - Optional keyStoreFile = Optional.ofNullable(props.getProperty(ES_KEY_STORE)); - if (keyStoreFile.isPresent()) { - setKeyStore(SearchDbConstants.SDB_SPECIFIC_CONFIG + keyStoreFile.get()); - } - - passwordValue = Optional.ofNullable(props.getProperty(ES_KEY_STORE_ENC)); - if (passwordValue.isPresent()) { - if(passwordValue.get().startsWith("OBF:")){ - setKeyStorePassword(Password.deobfuscate(passwordValue.get())); - }else if(passwordValue.get().startsWith("ENV:")){ - setKeyStorePassword(System.getenv(StringUtils.removeStart(passwordValue.get(), "ENV:"))); - } - else{ - setKeyStorePassword(passwordValue.get()); - } - } - } - - private void setUriScheme(String uriScheme) { - this.uriScheme = Optional.ofNullable(uriScheme).orElse(DEFAULT_URI_SCHEME); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java deleted file mode 100644 index 3d95a1b..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntity.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -public interface DocumentStoreDataEntity { - - public String getId(); - - public String getContentInJson(); - - public String getVersion(); - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java deleted file mode 100644 index 413dbb4..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreDataEntityImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -public class DocumentStoreDataEntityImpl implements DocumentStoreDataEntity { - - private String id; - private String content; - private String version; - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public void setId(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - @Override - public String getContentInJson() { - return content; - } - - @Override - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java deleted file mode 100644 index 5ea37e1..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/DocumentStoreInterface.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - - -import org.onap.aai.sa.rest.BulkRequest; -import org.onap.aai.sa.rest.DocumentSchema; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; - - -public interface DocumentStoreInterface { - - public OperationResult createIndex(String index, DocumentSchema documentSchema); - - public OperationResult createDynamicIndex(String index, String dynamicSchema); - - public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException; - - public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException; - - public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException; - - public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) - throws DocumentStoreOperationException; - - public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException; - - public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException; - - public SearchOperationResult search(String indexName, String queryText) throws DocumentStoreOperationException; - - public SearchOperationResult searchWithPayload(String indexName, String query) - throws DocumentStoreOperationException; - - - /** - * Forwards a set of operations to the document store as a single, bulk request. - * - * @param anIndex - The index to apply the operations to. - * @param operations - A java object containing the set of operations to be performed. - * @return - An operation result. - * @throws DocumentStoreOperationException - */ - public OperationResult performBulkOperations(BulkRequest[] request) throws DocumentStoreOperationException; -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java deleted file mode 100644 index 23181df..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchBulkOperationResult.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import java.util.Arrays; - -public class ElasticSearchBulkOperationResult { - - private Integer took; - private Boolean errors; - private ElasticSearchResultItem[] items; - - public ElasticSearchBulkOperationResult() { - - } - - public ElasticSearchResultItem[] getItems() { - return items; - } - - public void setItems(ElasticSearchResultItem[] items) { - this.items = items; - } - - public Integer getTook() { - return took; - } - - public void setTook(Integer took) { - this.took = took; - } - - public Boolean getErrors() { - return errors; - } - - public void setErrors(Boolean errors) { - this.errors = errors; - } - - @Override - public String toString() { - return "ElasticSearchOperationResult [took=" + took + ", errors=" + errors + ", items=" + Arrays.toString(items) - + "]"; - } - - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java deleted file mode 100644 index ee12494..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchCause.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -public class ElasticSearchCause { - - private String type; - private String reason; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java deleted file mode 100644 index 1880168..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import java.util.HashMap; -import java.util.Map; - -public class ElasticSearchError { - - private String type; - private String reason; - private ElasticSearchCause causedBy; - - private Map additionalProperties = new HashMap<>(); - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - public ElasticSearchCause getCausedBy() { - return causedBy; - } - - public void setCausedBy(ElasticSearchCause causedBy) { - this.causedBy = causedBy; - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperties(String name, Object value) { - additionalProperties.put(name, value); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java deleted file mode 100644 index a4af160..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java +++ /dev/null @@ -1,1410 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ - -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Throwables; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.ProtocolException; -import java.net.URL; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriBuilder; -import org.eclipse.jetty.http.HttpStatus; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.onap.aai.cl.api.LogFields; -import org.onap.aai.cl.api.LogLine; -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.cl.mdc.MdcOverride; -import org.onap.aai.sa.rest.AnalysisConfiguration; -import org.onap.aai.sa.rest.ApiUtils; -import org.onap.aai.sa.rest.BulkRequest; -import org.onap.aai.sa.rest.BulkRequest.OperationType; -import org.onap.aai.sa.rest.DocumentSchema; -import org.onap.aai.sa.rest.SettingConfiguration; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException.ErrorMessage; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; -import org.onap.aai.sa.searchdbabstraction.entity.Document; -import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.ErrorResult; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResultBuilder; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResultBuilder.Type; -import org.onap.aai.sa.searchdbabstraction.entity.SearchHit; -import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; -import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.SuggestHit; -import org.onap.aai.sa.searchdbabstraction.entity.SuggestHits; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.onap.aai.sa.searchdbabstraction.util.AggregationParsingUtil; -import org.onap.aai.sa.searchdbabstraction.util.DocumentSchemaUtil; -import org.onap.aai.sa.searchdbabstraction.util.ElasticSearchPayloadTranslator; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; - -/** - * This class has the Elasticsearch implementation of the DB operations defined in DocumentStoreInterface. - */ -public class ElasticSearchHttpController implements DocumentStoreInterface { - - private static ElasticSearchHttpController instance = null; - - private static final Logger logger = - LoggerFactory.getInstance().getLogger(ElasticSearchHttpController.class.getName()); - private static final Logger metricsLogger = - LoggerFactory.getInstance().getMetricsLogger(ElasticSearchHttpController.class.getName()); - - private static final String URL_QUERY_VERSION = "version="; - - private static final String JSON_ATTR_VERSION = "_version"; - private static final String JSON_ATTR_ERROR = "error"; - private static final String JSON_ATTR_REASON = "reason"; - - private static final String DEFAULT_TYPE = "default"; - - private static final String MSG_RESOURCE_MISSING = "Specified resource does not exist: "; - private static final String MSG_RESPONSE_CODE = "Response Code : "; - private static final String MSG_INVALID_DOCUMENT_URL = "Invalid document URL: "; - - private static final String FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE = "Failed to parse Elastic Search response."; - - private static final String BULK_CREATE_WITHOUT_INDEX_TEMPLATE = - "{\"create\":{\"_index\" : \"%s\", \"_type\" : \"%s\"} }\n"; - private static final String BULK_CREATE_WITH_INDEX_TEMPLATE = - "{\"create\":{\"_index\" : \"%s\", \"_type\" : \"%s\", \"_id\" : \"%s\" } }\n"; - private static final String BULK_IMPORT_INDEX_TEMPLATE = - "{\"index\":{\"_index\":\"%s\",\"_type\":\"%s\",\"_id\":\"%s\", \"_version\":\"%s\"}}\n"; - private static final String BULK_DELETE_TEMPLATE = - "{ \"delete\": { \"_index\": \"%s\", \"_type\": \"%s\", \"_id\": \"%s\", \"_version\":\"%s\"}}\n"; - public final static String APPLICATION_XND_JSON_TYPE = new MediaType("application", "x-ndjson").toString(); - - private final ElasticSearchConfig config; - - protected AnalysisConfiguration analysisConfig; - protected SettingConfiguration settingConfig; - - public ElasticSearchHttpController(ElasticSearchConfig config) { - this.config = config; - analysisConfig = new AnalysisConfiguration(); - settingConfig = new SettingConfiguration(); - - String rootUrl = null; - try { - if ("https".equals(config.getUriScheme())) { - new ElasticSearchHttpsController(config); - } - rootUrl = buildUrl(createUriBuilder("")).toString(); - logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_ATTEMPT, rootUrl); - checkConnection(); - logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_SUCCESS, rootUrl); - } catch (Exception e) { - logger.error(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_FAILURE, null, e, rootUrl, e.getMessage()); - } - } - - public static ElasticSearchHttpController getInstance() { - synchronized (ElasticSearchHttpController.class) { - if (instance == null) { - Properties properties = new Properties(); - File file = new File(SearchDbConstants.ES_CONFIG_FILE); - try { - properties.load(new FileInputStream(file)); - } catch (Exception e) { - logger.error(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "ElasticSearchHTTPController.getInstance", - e.getLocalizedMessage()); - } - - ElasticSearchConfig config = new ElasticSearchConfig(properties); - instance = new ElasticSearchHttpController(config); - } - } - - return instance; - } - - public AnalysisConfiguration getAnalysisConfig() { - return analysisConfig; - } - - public ElasticSearchConfig getElasticSearchConfig() { - return config; - } - - @Override - public OperationResult createIndex(String index, DocumentSchema documentSchema) { - try { - // Submit the request to ElasticSearch to create the index using a default document type. - OperationResult result = createTable(index, DEFAULT_TYPE, analysisConfig, - DocumentSchemaUtil.generateDocumentMappings(documentSchema), settingConfig); - - // ElasticSearch will return us a 200 code on success when we - // want to report a 201, so translate the result here. - if (result.getResultCode() == Status.OK.getStatusCode()) { - result.setResultCode(Status.CREATED.getStatusCode()); - } - - if (isSuccess(result)) { - result.setResult("{\"url\": \"" + ApiUtils.buildIndexUri(index) + "\"}"); - } - return result; - } catch (DocumentStoreOperationException | IOException e) { - return new OperationResultBuilder().useDefaults() - .failureCause("Document store operation failure. Cause: " + e.getMessage()).build(); - } - } - - @Override - public OperationResult createDynamicIndex(String index, String dynamicSchema) { - try { - OperationResult result = createTable(index, dynamicSchema); - - // ElasticSearch will return us a 200 code on success when we - // want to report a 201, so translate the result here. - if (result.getResultCode() == Status.OK.getStatusCode()) { - result.setResultCode(Status.CREATED.getStatusCode()); - } - if (isSuccess(result)) { - result.setResult("{\"url\": \"" + ApiUtils.buildIndexUri(index) + "\"}"); - } - return result; - } catch (DocumentStoreOperationException e) { - return new OperationResultBuilder().useDefaults() - .failureCause("Document store operation failure. Cause: " + e.getMessage()).build(); - } - } - - @Override - public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.DELETE); - OperationResult opResult = handleResponse(conn); - logMetricsInfo(override, SearchDbMsgs.DELETE_INDEX_TIME, opResult, indexName); - shutdownConnection(conn); - - return opResult; - } - - // @Override - protected OperationResult createTable(String indexName, String typeName, AnalysisConfiguration ac, - String indexMappings, SettingConfiguration sc) throws DocumentStoreOperationException { - if (ac.getEsIndexSettings() == null) { - logger.debug("No analysis settings provided."); - } - - if (indexMappings == null) { - logger.debug("No mappings provided."); - } - - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); - - StringBuilder sb = new StringBuilder(128); - sb.append("{ \"settings\" : "); - sb.append(sc.getSettingsWithAnalysis(ac)); - sb.append(","); - - sb.append("\"mappings\" : {"); - sb.append("\"" + typeName + "\" :"); - sb.append(indexMappings); - sb.append("}}"); - - try { - attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(sb.toString())); - } catch (IOException e) { - logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); - throw new DocumentStoreOperationException(e.getMessage(), e); - } - - logger.debug("Request content: " + sb); - - OperationResult opResult = handleResponse(conn); - shutdownConnection(conn); - logMetricsInfo(override, SearchDbMsgs.CREATE_INDEX_TIME, opResult, indexName); - - return opResult; - } - - /** - * Will send the passed in JSON payload to Elasticsearch using the provided index name in an attempt to create the - * index. - * - * @param indexName - The name of the index to be created - * @param settingsAndMappings - The actual JSON object that will define the index - * @return - The operation result of writing into Elasticsearch - * @throws DocumentStoreOperationException - */ - protected OperationResult createTable(String indexName, String settingsAndMappings) - throws DocumentStoreOperationException { - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); - try { - attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(settingsAndMappings)); - } catch (IOException e) { - logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); - throw new DocumentStoreOperationException(e.getMessage()); - } - - OperationResult result = handleResponse(conn); - logMetricsInfo(override, SearchDbMsgs.CREATE_INDEX_TIME, result, indexName); - - return result; - } - - @Override - public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { - - if (!allowImplicitIndexCreation) { - // Before we do anything, make sure that the specified index actually exists in the - // document store - we don't want to rely on ElasticSearch to fail the document - // create because it could be configured to implicitly create a non-existent index, - // which can lead to hard-to-debug behaviour with queries down the road. - OperationResult indexExistsResult = checkIndexExistence(indexName); - if (!isSuccess(indexExistsResult)) { - String resultMsg = "Document Index '" + indexName + "' does not exist."; - return (DocumentOperationResult) new OperationResultBuilder(Type.DOCUMENT).status(Status.NOT_FOUND) - .result(resultMsg).failureCause(resultMsg).build(); - } - } - - if (document.getId() == null || document.getId().isEmpty()) { - return createDocumentWithoutId(indexName, document); - } else { - return createDocumentWithId(indexName, document); - } - } - - @Override - public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { - if (!allowImplicitIndexCreation) { - // Before we do anything, make sure that the specified index actually exists in the - // document store - we don't want to rely on ElasticSearch to fail the document - // create because it could be configured to implicitly create a non-existent index, - // which can lead to hard-to-debug behaviour with queries down the road. - OperationResult indexExistsResult = checkIndexExistence(indexName); - if (!isSuccess(indexExistsResult)) { - DocumentOperationResult opResult = new DocumentOperationResult(); - opResult.setResultCode(Status.NOT_FOUND.getStatusCode()); - String resultMsg = "Document Index '" + indexName + "' does not exist."; - opResult.setResult(resultMsg); - opResult.setFailureCause(resultMsg); - return opResult; - } - } - - MdcOverride override = getStartTime(new MdcOverride()); - - final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) - .replaceQuery(URL_QUERY_VERSION + document.getVersion())); - - HttpURLConnection conn = createConnection(url, HttpMethod.PUT); - attachDocument(conn, document); - - DocumentOperationResult opResult = getOperationResult(conn); - buildDocumentResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.UPDATE_DOCUMENT_TIME, opResult, indexName, document.getId()); - - shutdownConnection(conn); - - return opResult; - } - - @Override - public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) - .replaceQuery(URL_QUERY_VERSION + document.getVersion())); - - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(url, HttpMethod.DELETE); - - DocumentOperationResult opResult = getOperationResult(conn); - buildDocumentResult(opResult, indexName); - // supress the etag and url in response for delete as they are not required - if (opResult.getDocument() != null) { - opResult.getDocument().setEtag(null); - opResult.getDocument().setUrl(null); - } - - logMetricsInfo(override, SearchDbMsgs.DELETE_DOCUMENT_TIME, opResult, indexName, document.getId()); - - shutdownConnection(conn); - - return opResult; - } - - @Override - public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - final UriBuilder uriBuilder = createUriBuilder(indexName, DEFAULT_TYPE, document.getId()); - if (document.getVersion() != null) { - uriBuilder.replaceQuery(URL_QUERY_VERSION + document.getVersion()); - } - - MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = createConnection(buildUrl(uriBuilder), "GET"); - - DocumentOperationResult opResult = getOperationResult(conn); - buildDocumentResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.GET_DOCUMENT_TIME, opResult, indexName, document.getId()); - - shutdownConnection(conn); - - return opResult; - } - - @Override - public SearchOperationResult search(String indexName, String queryString) throws DocumentStoreOperationException { - final URL url = buildUrl(createUriBuilder(indexName, "_search").replaceQuery(queryString)); - - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(url, "GET"); - SearchOperationResult opResult = getSearchOperationResult(conn); - buildSearchResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, queryString); - - return opResult; - } - - @Override - public SearchOperationResult searchWithPayload(String indexName, String query) - throws DocumentStoreOperationException { - if (logger.isDebugEnabled()) { - logger.debug("Querying index: " + indexName + " with query string: " + query); - } - final URL url = buildUrl(createUriBuilder(indexName, "_search")); - - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(url, HttpMethod.POST); - attachContent(conn, query); - logger.debug("Request body = Elasticsearch query = " + query); - - SearchOperationResult opResult = getSearchOperationResult(conn); - buildSearchResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, query); - - shutdownConnection(conn); - - return opResult; - } - - @Override - public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) - throws DocumentStoreOperationException { - if (logger.isDebugEnabled()) { - logger.debug("Querying Suggestion index: " + indexName + " with query string: " + query); - } - - MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName, "_suggest")), HttpMethod.POST); - attachContent(conn, query); - - logger.debug("Request body = Elasticsearch query = " + query); - - SearchOperationResult opResult = getSearchOperationResult(conn); - buildSuggestResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.QUERY_DOCUMENT_TIME, opResult, indexName, query); - - shutdownConnection(conn); - - return opResult; - } - - @Override - public OperationResult performBulkOperations(BulkRequest[] requests) throws DocumentStoreOperationException { - if (logger.isDebugEnabled()) { - StringBuilder dbgString = new StringBuilder("ESController: performBulkOperations - Operations: "); - - for (BulkRequest request : requests) { - dbgString.append("[").append(request).append("] "); - } - - logger.debug(dbgString.toString()); - } - - MdcOverride override = getStartTime(new MdcOverride()); - - // Parse the supplied set of operations. - // Iterate over the list of operations which we were provided and - // translate them into a format that ElasticSearh understands. - int opCount = 0; - StringBuilder esOperationSet = new StringBuilder(128); - List rejected = new ArrayList<>(); - for (BulkRequest request : requests) { - - // Convert the request to the syntax ElasticSearch likes. - if (buildEsOperation(request, esOperationSet, rejected)) { - opCount++; - } - } - - ElasticSearchBulkOperationResult opResult = null; - if (opCount > 0) { - HttpURLConnection conn; - try { - conn = (HttpURLConnection) buildUrl(createUriBuilder("_bulk")).openConnection(); - conn.setRequestMethod(HttpMethod.PUT); - conn.setDoOutput(true); - conn.setRequestProperty(CONTENT_TYPE, APPLICATION_XND_JSON_TYPE); - if(config.useAuth()){ - conn.setRequestProperty("Authorization", config.getAuthValue()); - } - conn.setRequestProperty("Connection", "Close"); - - } catch (IOException e) { - - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug(Throwables.getStackTraceAsString(e)); - } - - throw new DocumentStoreOperationException( - "Failed to open connection to document store. Cause: " + e.getMessage(), e); - } - - StringBuilder bulkResult = new StringBuilder(128); - try { - // Create an output stream to write our request to. - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - - if (logger.isDebugEnabled()) { - logger.debug("ESController: Sending 'BULK' request to " + conn.getURL()); - logger.debug("ESController: operations: " + esOperationSet.toString().replaceAll("\n", "\\n")); - } - - // Write the resulting request string to our output stream. (this sends the request to ES?) - out.write(esOperationSet.toString()); - out.close(); - - // Open an input stream on our connection in order to read back the results. - InputStream is = conn.getInputStream(); - InputStreamReader inputstreamreader = new InputStreamReader(is); - BufferedReader bufferedreader = new BufferedReader(inputstreamreader); - - // Read the contents of the input stream into our result string... - String esResponseString = null; - - while ((esResponseString = bufferedreader.readLine()) != null) { - bulkResult.append(esResponseString).append("\n"); - } - - } catch (IOException e) { - - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); - if (logger.isDebugEnabled()) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - logger.debug(sw.toString()); - } - - throw new DocumentStoreOperationException( - "Failure interacting with document store. Cause: " + e.getMessage(), e); - } - - if (logger.isDebugEnabled()) { - logger.debug("ESController: Received result string from ElasticSearch: = " + bulkResult.toString()); - } - - // ...and marshal the resulting string into a Java object. - try { - opResult = marshallEsBulkResult(bulkResult.toString()); - - } catch (IOException e) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug(Throwables.getStackTraceAsString(e)); - } - - throw new DocumentStoreOperationException("Failed to marshal response body. Cause: " + e.getMessage(), - e); - } - } - - OperationResult result = new OperationResultBuilder() // - .resultCode(HttpStatus.MULTI_STATUS_207) // - .result(buildGenericBulkResultSet(opResult, rejected)) // - .build(); - - // In the success case we don't want the entire result string to be dumped into the metrics log, so concatenate - // it. - String resultStringForMetricsLog = result.getResult(); - if (isSuccess(result)) { - resultStringForMetricsLog = - resultStringForMetricsLog.substring(0, Math.max(resultStringForMetricsLog.length(), 85)) + "..."; - } - - metricsLogger.info(SearchDbMsgs.BULK_OPERATIONS_TIME, - new LogFields() // - .setField(LogLine.DefinedFields.RESPONSE_CODE, result.getResultCode()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, resultStringForMetricsLog), - override); - - return result; - } - - - /** - * This method queryies ElasticSearch to determine if the supplied index is present in the document store. - * - * @param indexName - The index to look for. - * @return - An operation result indicating the success or failure of the check. - * @throws DocumentStoreOperationException - */ - private OperationResult checkIndexExistence(String indexName) throws DocumentStoreOperationException { - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.HEAD); - int resultCode; - try { - resultCode = conn.getResponseCode(); - } catch (IOException ex) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); - } - logger.debug(MSG_RESPONSE_CODE + resultCode); - - OperationResult opResult = new OperationResultBuilder().useDefaults().resultCode(resultCode).build(); - logMetricsInfo(override, SearchDbMsgs.CHECK_INDEX_TIME, opResult, indexName); - shutdownConnection(conn); - - return opResult; - } - - private DocumentOperationResult createDocumentWithId(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - // check if the document already exists - DocumentOperationResult opResult = checkDocumentExistence(indexName, document.getId()); - - if (opResult.getResultCode() != Status.NOT_FOUND.getStatusCode()) { - if (opResult.getResultCode() == Status.CONFLICT.getStatusCode()) { - opResult.setFailureCause("A document with the same id already exists."); - } else { - opResult.setFailureCause("Failed to verify a document with the specified id does not already exist."); - } - opResult.setResultCode(Status.CONFLICT.getStatusCode()); - return opResult; - } - - final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId())); - MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = createConnection(url, HttpMethod.PUT); - attachDocument(conn, document); - - opResult = getOperationResult(conn); - buildDocumentResult(opResult, indexName); - - logMetricsInfo(override, SearchDbMsgs.CREATE_DOCUMENT_TIME, opResult, indexName); - - shutdownConnection(conn); - - return opResult; - } - - private DocumentOperationResult createDocumentWithoutId(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE)); - - MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = createConnection(url, HttpMethod.POST); - attachDocument(conn, document); - - DocumentOperationResult response = getOperationResult(conn); - buildDocumentResult(response, indexName); - - logMetricsInfo(override, SearchDbMsgs.CREATE_DOCUMENT_TIME, response, indexName); - - shutdownConnection(conn); - - return response; - } - - private void attachDocument(HttpURLConnection conn, DocumentStoreDataEntity doc) - throws DocumentStoreOperationException { - conn.setRequestProperty("Connection", "Close"); - attachContent(conn, doc.getContentInJson()); - } - - private DocumentOperationResult checkDocumentExistence(String indexName, String docId) - throws DocumentStoreOperationException { - MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = - createConnection(buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, docId)), HttpMethod.HEAD); - int resultCode; - try { - resultCode = conn.getResponseCode(); - } catch (IOException ex) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); - } - - logger.debug(MSG_RESPONSE_CODE + resultCode); - - DocumentOperationResult opResult = (DocumentOperationResult) new OperationResultBuilder(Type.DOCUMENT) - .useDefaults().resultCode(resultCode).build(); - - logMetricsInfo(override, SearchDbMsgs.GET_DOCUMENT_TIME, opResult, indexName, docId); - shutdownConnection(conn); - - return opResult; - } - - private void attachContent(HttpURLConnection conn, String content) throws DocumentStoreOperationException { - OutputStream outputStream = null; - OutputStreamWriter out = null; - - try { - outputStream = conn.getOutputStream(); - } catch (IOException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to get connection output stream.", e); - } - - out = new OutputStreamWriter(outputStream); - - try { - out.write(content); - out.close(); - } catch (IOException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to write to the output stream.", e); - } - } - - private HttpURLConnection initializeConnection(URL url) throws DocumentStoreOperationException { - HttpURLConnection conn = null; - try { - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON); - conn.setDoOutput(true); - if (config.useAuth()) { - conn.setRequestProperty("Authorization", config.getAuthValue()); - } - } catch (IOException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to open connection to URL " + url, e); - } - - return conn; - } - - private OperationResult handleResponse(HttpURLConnection conn) throws DocumentStoreOperationException { - return handleResponse(conn, new OperationResultBuilder().useDefaults()); - } - - private OperationResult handleResponse(HttpURLConnection conn, OperationResultBuilder rb) - throws DocumentStoreOperationException { - int resultCode; - - try { - resultCode = conn.getResponseCode(); - } catch (IOException ex) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); - } - - logger.debug(MSG_RESPONSE_CODE + resultCode); - - InputStream inputStream = null; - - if (!ApiUtils.isSuccessStatusCode(resultCode)) { - inputStream = conn.getErrorStream(); - } else { - try { - inputStream = conn.getInputStream(); - } catch (IOException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to get the response input stream.", e); - } - } - - InputStreamReader inputstreamreader = new InputStreamReader(inputStream); - BufferedReader bufferedreader = new BufferedReader(inputstreamreader); - - StringBuilder result = new StringBuilder(128); - String string = null; - - try { - while ((string = bufferedreader.readLine()) != null) { - result.append(string).append("\n"); - } - } catch (IOException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed getting the response body payload.", e); - } - - if (resultCode == Status.CONFLICT.getStatusCode()) { - rb.resultCode(Status.PRECONDITION_FAILED.getStatusCode()); - } else { - rb.resultCode(resultCode); - } - if (logger.isDebugEnabled()) { - logger.debug("Raw result string from ElasticSearch = " + result.toString()); - } - rb.result(result.toString()); - rb.resultVersion(extractVersion(result.toString())); - return rb.build(); - } - - private String extractVersion(String result) { - JSONParser parser = new JSONParser(); - String version = null; - try { - JSONObject root = (JSONObject) parser.parse(result); - if (root.get(JSON_ATTR_VERSION) != null) { - version = root.get(JSON_ATTR_VERSION).toString(); - } - } catch (ParseException e) { - // Not all responses from ElasticSearch include a version, so - // if we don't get one back, just return an empty string rather - // than trigger a false failure. - version = ""; - } - return version; - } - - /** - * This convenience method gets the current system time and stores it in an attribute in the supplied - * {@link MdcOverride} object so that it can be used later by the metrics logger. - * - * @param override - The {@link MdcOverride} object to update. - * @return - The supplied {@link MdcOverride} object. - */ - private MdcOverride getStartTime(MdcOverride override) { - - // Grab the current time... - long startTimeInMs = System.currentTimeMillis(); - - // ...and add it as an attribute to the supplied MDC Override object. - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); - override.addAttribute(MdcContext.MDC_START_TIME, formatter.format(startTimeInMs)); - - // Return the MdcOverride object that we were passed. - // This looks odd, but it allows us to do stuff like: - // - // MdcOverride ov = getStartTime(new MdcOverride()) - // - // which is quite handy, but also allows us to pass in an existing - // MdcOverride object which already has some attributes set. - return override; - } - - private boolean isSuccess(OperationResult result) { - return ApiUtils.isSuccessStatusCode(result.getResultCode()); - } - - private UriBuilder createUriBuilder(String path, String... paths) { - UriBuilder builder = UriBuilder.fromPath(path); - for (String other : paths) { - builder.path(other); - } - builder.host(config.getIpAddress()); - String port = Optional.ofNullable(config.getHttpPort()).orElse("0"); - builder.port(Integer.valueOf(port)); - builder.scheme(config.getUriScheme()); - return builder; - } - - private URL buildUrl(UriBuilder builder) throws DocumentStoreOperationException { - try { - return builder.build().toURL(); - } catch (MalformedURLException e) { - logger.error(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "buildUrl", e.getLocalizedMessage()); - throw new DocumentStoreOperationException("Error building a URL with " + builder.toString(), e); - } - } - - private HttpURLConnection createConnection(final URL url, final String method) - throws DocumentStoreOperationException { - HttpURLConnection conn = initializeConnection(url); - try { - logger.debug("\nSending '" + method + "' request to URL : " + conn.getURL()); - conn.setRequestMethod(method); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(ErrorMessage.SET_REQUEST_METHOD_FAILED, e, method); - } - return conn; - } - - private OperationResult checkConnection() throws IOException, DocumentStoreOperationException { - HttpURLConnection conn = createConnection(buildUrl(createUriBuilder("_cluster/health")), HttpMethod.GET); - int resultCode = conn.getResponseCode(); - logger.debug("getClusterHealth() response Code : " + resultCode); - shutdownConnection(conn); - return new OperationResultBuilder().resultCode(resultCode).build(); - } - - private void shutdownConnection(HttpURLConnection connection) { - if (connection == null) { - return; - } - - final String methodName = "shutdownConnection"; - InputStream inputstream = null; - OutputStream outputstream = null; - - try { - inputstream = connection.getInputStream(); - } catch (IOException e) { - logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); - } finally { - if (inputstream != null) { - try { - inputstream.close(); - } catch (IOException e) { - logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); - } - } - } - - try { - outputstream = connection.getOutputStream(); - } catch (IOException e) { - logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); - } finally { - if (outputstream != null) { - try { - outputstream.close(); - } catch (IOException e) { - logger.debug(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, methodName, e.getLocalizedMessage()); - } - } - } - - connection.disconnect(); - } - - /** - * This method converts a {@link BulkRequest} object into a json structure which can be understood by ElasticSearch. - * - * @param request - The request to be performed. - * @param sb - The string builder to append the json data to - * @throws DocumentStoreOperationException - */ - private boolean buildEsOperation(BulkRequest request, StringBuilder sb, List fails) - throws DocumentStoreOperationException { - - boolean retVal = true; - // What kind of operation are we performing? - switch (request.getOperationType()) { - - // Create a new document. - case CREATE: - - // Make sure that we were supplied a document payload. - if (request.getOperation().getDocument() == null) { - - fails.add(generateRejectionEntry(request.getOperationType(), "Missing document payload", - request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Make sure that the supplied document URL is formatted - // correctly. - if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), false)) { - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), - request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Validate that the specified index actually exists before we - // try to perform the create. - if (!indexExists(ApiUtils.extractIndexFromUri(request.getOperation().getMetaData().getUrl()))) { - - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), - request.getId(), 404, request.getOperation().getMetaData().getUrl())); - return false; - } - - // If we were supplied an id for the new document, then - // include it in the bulk operation to Elastic Search - if (request.getId() == null) { - - sb.append(String.format(BULK_CREATE_WITHOUT_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE)); - - // Otherwise, we just leave that parameter off and ElasticSearch - // will generate one for us. - } else { - sb.append(String.format(BULK_CREATE_WITH_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE, - request.getId())); - } - - try { - // Append the document that we want to create. - sb.append(request.getOperation().getDocument().toJson()).append("\n"); - } catch (JsonProcessingException e) { - throw new DocumentStoreOperationException("Failure parsing document to json", e); - } - - break; - - // Update an existing document. - case UPDATE: - - // Make sure that we were supplied a document payload. - if (request.getOperation().getDocument() == null) { - - fails.add(generateRejectionEntry(request.getOperationType(), "Missing document payload", - request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Make sure that the supplied document URL is formatted - // correctly. - if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), true)) { - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), - request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Validate that the specified index actually exists before we - // try to perform the update. - if (!indexExists(request.getIndex())) { - - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), - request.getId(), 404, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Validate that the document we are trying to update actually - // exists before we try to perform the update. - if (!documentExists(request.getIndex(), request.getId())) { - - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), - request.getId(), 404, request.getOperation().getMetaData().getUrl())); - return false; - } - - // It is mandatory that a version be supplied for an update operation, - // so validate that now. - if (request.getOperation().getMetaData().getEtag() == null) { - - fails.add(generateRejectionEntry(request.getOperationType(), "Missing mandatory ETag field", - request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Generate the update request... - sb.append(String.format(BULK_IMPORT_INDEX_TEMPLATE, request.getIndex(), DEFAULT_TYPE, request.getId(), - request.getOperation().getMetaData().getEtag())); - - // ...and append the document that we want to update. - try { - sb.append(request.getOperation().getDocument().toJson()).append("\n"); - } catch (JsonProcessingException e) { - throw new DocumentStoreOperationException("Failure parsing document to json", e); - } - break; - - // Delete an existing document. - case DELETE: - - // Make sure that the supplied document URL is formatted - // correctly. - if (!ApiUtils.validateDocumentUri(request.getOperation().getMetaData().getUrl(), true)) { - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_INVALID_DOCUMENT_URL + request.getOperation().getMetaData().getUrl(), - request.getIndex(), "", 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Validate that the specified index actually exists before we - // try to perform the delete. - if (!indexExists(request.getIndex())) { - - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), - request.getId(), 404, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Validate that the document we are trying to update actually - // exists before we try to perform the delete. - if (!documentExists(request.getIndex(), request.getId())) { - - fails.add(generateRejectionEntry(request.getOperationType(), - MSG_RESOURCE_MISSING + request.getOperation().getMetaData().getUrl(), request.getIndex(), - request.getId(), 404, request.getOperation().getMetaData().getUrl())); - return false; - } - - // It is mandatory that a version be supplied for a delete operation, - // so validate that now. - if (request.getOperation().getMetaData().getEtag() == null) { - - fails.add(generateRejectionEntry(request.getOperationType(), "Missing mandatory ETag field", - request.getIndex(), request.getId(), 400, request.getOperation().getMetaData().getUrl())); - return false; - } - - // Generate the delete request. - sb.append(String.format(BULK_DELETE_TEMPLATE, request.getIndex(), DEFAULT_TYPE, request.getId(), - request.getOperation().getMetaData().getEtag())); - break; - default: - } - - return retVal; - } - - private boolean indexExists(String index) throws DocumentStoreOperationException { - return isSuccess(checkIndexExistence(index)); - } - - private boolean documentExists(String index, String id) throws DocumentStoreOperationException { - return isSuccess(checkDocumentExistence(index, id)); - } - - /** - * This method constructs a status entry for a bulk operation which has been rejected before even sending it to the - * document store. - * - * @param rejectReason - A message describing why the operation was rejected. - * @param anId - The identifier associated with the document being acted on. - * @param statusCode - An HTTP status code. - * @return - A result set item. - */ - private ElasticSearchResultItem generateRejectionEntry(OperationType opType, String rejectReason, String index, - String anId, int statusCode, String originalUrl) { - - ElasticSearchError err = new ElasticSearchError(); - err.setReason(rejectReason); - - ElasticSearchOperationStatus op = new ElasticSearchOperationStatus(); - op.setIndex(index); - op.setId(anId); - op.setStatus(statusCode); - op.setError(err); - op.setAdditionalProperties(ElasticSearchResultItem.REQUEST_URL, originalUrl); - - ElasticSearchResultItem rejectionResult = new ElasticSearchResultItem(); - - switch (opType) { - case CREATE: - rejectionResult.setCreate(op); - break; - case UPDATE: - rejectionResult.setIndex(op); - break; - case DELETE: - rejectionResult.setDelete(op); - break; - default: - } - - return rejectionResult; - } - - /** - * This method takes the json structure returned from ElasticSearch in response to a bulk operations request and - * marshals it into a Java object. - * - * @param jsonResult - The bulk operations response returned from ElasticSearch. - * @return - The marshalled response. - * @throws JsonParseException - * @throws JsonMappingException - * @throws IOException - */ - private ElasticSearchBulkOperationResult marshallEsBulkResult(String jsonResult) throws IOException { - if (jsonResult != null) { - if (logger.isDebugEnabled()) { - logger.debug("ESController: Marshalling ES result set from json: " + jsonResult.replaceAll("\n", "")); - } - - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(Include.NON_EMPTY); - - return mapper.readValue(jsonResult, ElasticSearchBulkOperationResult.class); - } - - return null; - } - - /** - * This method takes the marshalled ElasticSearch bulk response and converts it into a generic response payload. - * - * @param esResult - ElasticSearch bulk operations response. - * @return - A generic result set. - */ - private String buildGenericBulkResultSet(ElasticSearchBulkOperationResult esResult, - List rejectedOps) { - int totalOps = 0; - int totalSuccess = 0; - int totalFails = 0; - - if (logger.isDebugEnabled()) { - - logger.debug("ESController: Build generic result set. ES Results: " - + ((esResult != null) ? esResult.toString() : "[]") + " Rejected Ops: " + rejectedOps.toString()); - } - - // Build a combined list of result items from the results returned - // from ElasticSearch and the list of operations that we rejected - // without sending to ElasticSearch. - List combinedResults = new ArrayList<>(); - if (esResult != null) { - combinedResults.addAll(Arrays.asList(esResult.getItems())); - } - combinedResults.addAll(rejectedOps); - - // Iterate over the individual results in the resulting result set. - StringBuilder resultsBuilder = new StringBuilder(); - AtomicBoolean firstItem = new AtomicBoolean(true); - for (ElasticSearchResultItem item : combinedResults) { - - // Increment the operation counts. - totalOps++; - if (ApiUtils.isSuccessStatusCode(item.operationStatus().getStatus())) { - totalSuccess++; - } else { - totalFails++; - } - - // Prepend a comma to our response string unless this it the - // first result in the set. - if (!firstItem.compareAndSet(true, false)) { - resultsBuilder.append(", "); - } - - // Append the current result as a generic json structure. - resultsBuilder.append(item.toJson()); - } - - return "{ \"total_operations\": " + totalOps + ", " + "\"total_success\": " + totalSuccess + ", " - + "\"total_fails\": " + totalFails + ", " + "\"results\": [" + resultsBuilder.toString() + "]}"; - } - - private DocumentOperationResult getOperationResult(HttpURLConnection conn) throws DocumentStoreOperationException { - return (DocumentOperationResult) handleResponse(conn, new OperationResultBuilder(Type.DOCUMENT).useDefaults()); - } - - private SearchOperationResult getSearchOperationResult(HttpURLConnection conn) - throws DocumentStoreOperationException { - return (SearchOperationResult) handleResponse(conn, new OperationResultBuilder(Type.SEARCH).useDefaults()); - } - - private void buildDocumentResult(DocumentOperationResult result, String index) - throws DocumentStoreOperationException { - - JSONParser parser = new JSONParser(); - JSONObject root; - try { - root = (JSONObject) parser.parse(result.getResult()); - if (isSuccess(result)) { - // Success response object - Document doc = new Document(); - doc.setEtag(result.getResultVersion()); - doc.setUrl(buildDocumentResponseUrl(index, root.get("_id").toString())); - - doc.setContent((JSONObject) root.get("_source")); - result.setDocument(doc); - - } else { - // Error response object - JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); - if (error != null) { - result.setError( - new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); - } - - } - } catch (Exception e) { - throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); - } - } - - private String buildDocumentResponseUrl(String index, String id) { - return ApiUtils.buildDocumentUri(index, id); - } - - private void buildSearchResult(SearchOperationResult result, String index) throws DocumentStoreOperationException { - JSONParser parser = new JSONParser(); - JSONObject root; - - try { - root = (JSONObject) parser.parse(result.getResult()); - if (isSuccess(result)) { - JSONObject hits = (JSONObject) root.get("hits"); - JSONArray hitArray = (JSONArray) hits.get("hits"); - SearchHits searchHits = new SearchHits(); - searchHits.setTotalHits(hits.get("total").toString()); - ArrayList searchHitArray = new ArrayList<>(); - - for (int i = 0; i < hitArray.size(); i++) { - JSONObject hit = (JSONObject) hitArray.get(i); - SearchHit searchHit = new SearchHit(); - searchHit.setScore((hit.get("_score") != null) ? hit.get("_score").toString() : ""); - Document doc = new Document(); - if (hit.get(JSON_ATTR_VERSION) != null) { - doc.setEtag((hit.get(JSON_ATTR_VERSION) != null) ? hit.get(JSON_ATTR_VERSION).toString() : ""); - } - - doc.setUrl( - buildDocumentResponseUrl(index, (hit.get("_id") != null) ? hit.get("_id").toString() : "")); - doc.setContent((JSONObject) hit.get("_source")); - searchHit.setDocument(doc); - searchHitArray.add(searchHit); - } - searchHits.setHits(searchHitArray.toArray(new SearchHit[searchHitArray.size()])); - result.setSearchResult(searchHits); - - JSONObject aggregations = (JSONObject) root.get("aggregations"); - if (aggregations != null) { - AggregationResult[] aggResults = AggregationParsingUtil.parseAggregationResults(aggregations); - AggregationResults aggs = new AggregationResults(); - aggs.setAggregations(aggResults); - result.setAggregationResult(aggs); - } - - // success - } else { - JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); - if (error != null) { - result.setError( - new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); - } - } - } catch (Exception e) { - throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); - } - } - - private void buildSuggestResult(SearchOperationResult result, String index) throws DocumentStoreOperationException { - JSONParser parser = new JSONParser(); - JSONObject root; - try { - root = (JSONObject) parser.parse(result.getResult()); - if (isSuccess(result)) { - JSONArray hitArray = (JSONArray) root.get("suggest-vnf"); - JSONObject hitdata = (JSONObject) hitArray.get(0); - JSONArray optionsArray = (JSONArray) hitdata.get("options"); - SuggestHits suggestHits = new SuggestHits(); - suggestHits.setTotalHits(String.valueOf(optionsArray.size())); - - ArrayList suggestHitArray = new ArrayList<>(); - - for (int i = 0; i < optionsArray.size(); i++) { - JSONObject hit = (JSONObject) optionsArray.get(i); - - SuggestHit suggestHit = new SuggestHit(); - suggestHit.setScore((hit.get("score") != null) ? hit.get("score").toString() : ""); - suggestHit.setText((hit.get("text") != null) ? hit.get("text").toString() : ""); - Document doc = new Document(); - if (hit.get(JSON_ATTR_VERSION) != null) { - doc.setEtag((hit.get(JSON_ATTR_VERSION) != null) ? hit.get(JSON_ATTR_VERSION).toString() : ""); - } - doc.setUrl( - buildDocumentResponseUrl(index, (hit.get("_id") != null) ? hit.get("_id").toString() : "")); - - doc.setContent((JSONObject) hit.get("payload")); - suggestHit.setDocument(doc); - suggestHitArray.add(suggestHit); - } - suggestHits.setHits(suggestHitArray.toArray(new SuggestHit[suggestHitArray.size()])); - result.setSuggestResult(suggestHits); - - JSONObject aggregations = (JSONObject) root.get("aggregations"); - if (aggregations != null) { - AggregationResult[] aggResults = AggregationParsingUtil.parseAggregationResults(aggregations); - AggregationResults aggs = new AggregationResults(); - aggs.setAggregations(aggResults); - result.setAggregationResult(aggs); - } - - // success - } else { - JSONObject error = (JSONObject) root.get(JSON_ATTR_ERROR); - if (error != null) { - result.setError( - new ErrorResult(error.get("type").toString(), error.get(JSON_ATTR_REASON).toString())); - } - } - } catch (Exception e) { - throw new DocumentStoreOperationException(FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE + result.getResult()); - } - } - - /** - * Record the timing of the operation in the metrics log. - * - */ - private void logMetricsInfo(MdcOverride override, SearchDbMsgs message, OperationResult operationResult, - String... args) { - metricsLogger.info(message, - new LogFields() // - .setField(LogLine.DefinedFields.RESPONSE_CODE, operationResult.getResultCode()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, operationResult.getResult()) - .setField(LogLine.DefinedFields.SERVER_IP, "ElasticHost-"+config.getIpAddress()), - override, args); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java deleted file mode 100644 index 51b8952..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpsController.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; - -/** - * HTTPS (TLS) specific configuration. - */ -public class ElasticSearchHttpsController { - - private static final Logger logger = - LoggerFactory.getInstance().getLogger(ElasticSearchHttpsController.class.getName()); - - private static final String SSL_PROTOCOL = "TLS"; - private static final String KEYSTORE_ALGORITHM = "SunX509"; - private static final String KEYSTORE_TYPE = "PKCS12"; - - public ElasticSearchHttpsController(ElasticSearchConfig config) throws NoSuchAlgorithmException, KeyStoreException, - CertificateException, IOException, KeyManagementException, UnrecoverableKeyException { - logger.debug("Initialising HTTPS configuration"); - - SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); - KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); - - String clientCertPassword = config.getKeyStorePassword(); - - char[] pwd = null; - if (clientCertPassword != null) { - pwd = clientCertPassword.toCharArray(); - } else { - logger.debug("No key store password is defined"); - } - - TrustManager[] trustManagers = getTrustManagers(config); - KeyManager[] keyManagers = null; - - String clientCertFileName = config.getKeyStorePath(); - if (clientCertFileName != null) { - InputStream fin = Files.newInputStream(Paths.get(clientCertFileName)); - keyStore.load(fin, pwd); - kmf.init(keyStore, pwd); - keyManagers = kmf.getKeyManagers(); - } - - ctx.init(keyManagers, trustManagers, null); - logger.debug("Initialised SSL context"); - - HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> host.equalsIgnoreCase(session.getPeerHost())); - } - - private TrustManager[] getTrustManagers(ElasticSearchConfig config) - throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException { - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - // Using null here initializes the TMF with the default trust store. - tmf.init((KeyStore) null); - - // Find the default trust manager. - final X509TrustManager defaultTrustManager = findX509TrustManager(tmf); - - String trustStoreFile = config.getTrustStorePath(); - if (trustStoreFile == null) { - logger.debug("No trust store defined"); - return new TrustManager[] {defaultTrustManager}; - } - - // Create a new Trust Manager from the local trust store. - try (InputStream myKeys = Files.newInputStream(Paths.get(trustStoreFile))) { - KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - char[] pwdArray = null; - if (config.getTrustStorePassword() != null) { - pwdArray = config.getTrustStorePassword().toCharArray(); - } - myTrustStore.load(myKeys, pwdArray); - tmf.init(myTrustStore); - } - - // Create a custom trust manager that wraps both our trust store and the default. - final X509TrustManager finalLocalTm = findX509TrustManager(tmf); - - return new TrustManager[] {new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return defaultTrustManager.getAcceptedIssuers(); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - try { - finalLocalTm.checkServerTrusted(chain, authType); - } catch (CertificateException e) { - defaultTrustManager.checkServerTrusted(chain, authType); - } - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - defaultTrustManager.checkClientTrusted(chain, authType); - } - }}; - } - - private X509TrustManager findX509TrustManager(TrustManagerFactory tmf) { - return (X509TrustManager) Arrays.asList(tmf.getTrustManagers()).stream() - .filter(tm -> tm instanceof X509TrustManager).findFirst().orElse(null); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java deleted file mode 100644 index 6374716..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import java.util.HashMap; -import java.util.Map; - -public class ElasticSearchOperationStatus { - - private String index; - private String type; - private String id; - private String version; - private ElasticSearchShardStatus shards; - private Integer status; - private ElasticSearchError error; - - private Map additionalProperties = new HashMap<>(); - - public ElasticSearchError getError() { - return error; - } - - public void setError(ElasticSearchError error) { - this.error = error; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public ElasticSearchShardStatus getShards() { - return shards; - } - - public void setShards(ElasticSearchShardStatus shards) { - this.shards = shards; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperties(String name, Object value) { - additionalProperties.put(name, value); - } - - @Override - public String toString() { - return "ElasticSearchIndexStatus [index=" + index + ", type=" + type + ", id=" + id + ", version=" + version - + ", shards=" + shards + ", status=" + status + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java deleted file mode 100644 index 151e02b..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import org.onap.aai.sa.rest.ApiUtils; - -public class ElasticSearchResultItem { - - public static final String REQUEST_URL = "REQUEST_URL"; - - private ElasticSearchOperationStatus create; - private ElasticSearchOperationStatus index; - private ElasticSearchOperationStatus delete; - - public ElasticSearchOperationStatus getCreate() { - return create; - } - - public void setCreate(ElasticSearchOperationStatus index) { - this.create = index; - } - - public ElasticSearchOperationStatus getIndex() { - return index; - } - - public void setIndex(ElasticSearchOperationStatus index) { - this.index = index; - } - - public ElasticSearchOperationStatus getDelete() { - return delete; - } - - public void setDelete(ElasticSearchOperationStatus delete) { - this.delete = delete; - } - - public String operationType() { - - if (create != null) { - return "create"; - } - if (index != null) { - return "update"; - } - if (delete != null) { - return "delete"; - } - - return "unknown"; - } - - public ElasticSearchOperationStatus operationStatus() { - - if (create != null) { - return create; - } - if (index != null) { - return index; - } - if (delete != null) { - return delete; - } - - return null; - } - - - public String toJson() { - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - sb.append("\"operation\": \"").append(operationType()).append("\", "); - - if (operationStatus().getAdditionalProperties().containsKey(REQUEST_URL)) { - sb.append("\"url\": \"").append(operationStatus().getAdditionalProperties().get(REQUEST_URL)) - .append("\", "); - } else { - sb.append("\"url\": \"") - .append(ApiUtils.buildDocumentUri(operationStatus().getIndex(), operationStatus().getId())) - .append("\", "); - } - - // We don't want to include an etag field in the response in - // the case of a delete, since that would imply that the client - // could still access that version of the file in some manner - // (which we are not supporting). - if (!operationType().equals("delete")) { - sb.append("\"etag\": \"").append(operationStatus().getVersion()).append("\", "); - } - sb.append("\"status-code\": \"").append(operationStatus().getStatus()).append("\", "); - - sb.append("\"status-message\": \""); - - if (ApiUtils.isSuccessStatusCode(operationStatus().getStatus())) { - sb.append("OK"); - } else { - // Sometimes the error object doesn't get populated, so check - // before we try to reference it... - if (operationStatus().getError() != null) { - sb.append(operationStatus().getError().getReason()); - } else { - sb.append(""); - } - } - sb.append("\""); - sb.append("}"); - - return sb.toString(); - } - - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append("ElasticSearchItemStatus ["); - if (create != null) { - sb.append("create " + create); - } else if (index != null) { - sb.append("index " + index); - } else if (delete != null) { - sb.append("delete " + index); - } - sb.append("]"); - return sb.toString(); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java deleted file mode 100644 index e846a38..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchShardStatus.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -public class ElasticSearchShardStatus { - - private int total; - private int successful; - private int failed; - - public int getTotal() { - return total; - } - - public void setTotal(int total) { - this.total = total; - } - - public int getSuccessful() { - return successful; - } - - public void setSuccessful(int successful) { - this.successful = successful; - } - - public int getFailed() { - return failed; - } - - public void setFailed(int failed) { - this.failed = failed; - } - - @Override - public String toString() { - return "ElasticSearchShardStatus [total=" + total + ", successful=" + successful + ", failed=" + failed + "]"; - } - - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java deleted file mode 100644 index 7db6c4e..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.exception; - -public class DocumentStoreOperationException extends Exception { - - private static final long serialVersionUID = -7689309913743200670L; - - public enum ErrorMessage { - NO_RESPONSE_CODE( - "Failed to get the response code from the connection." - ), - SET_REQUEST_METHOD_FAILED( - "Failed to set HTTP request method to %s." - ); - private String message; - - ErrorMessage(String msg) { - this.message = msg; - } - } - - public DocumentStoreOperationException(ErrorMessage error, Exception ex, Object... args) { - super(String.format(error.message, args), ex); - } - - public DocumentStoreOperationException(String message, Exception ex) { - super(message, ex); - } - - public DocumentStoreOperationException(String message) { - super(message); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java deleted file mode 100644 index ae0a3e9..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationBucket.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Arrays; - -public class AggregationBucket { - private Object key; - - @JsonProperty("formatted-key") - private String formattedKey; - - private Number count; - - @JsonProperty("sub-aggregations") - private AggregationResult[] subAggregationResult; - - public Object getKey() { - return key; - } - - public void setKey(Object key) { - this.key = key; - } - - public String getFormattedKey() { - return formattedKey; - } - - public void setFormattedKey(String formattedKey) { - this.formattedKey = formattedKey; - } - - public Number getCount() { - return count; - } - - public void setCount(Number count) { - this.count = count; - } - - public AggregationResult[] getSubAggregationResult() { - return subAggregationResult; - } - - public void setSubAggregationResult(AggregationResult[] subAggregationResult) { - this.subAggregationResult = subAggregationResult; - } - - @Override - public String toString() { - return "AggregationBucket [key=" + key + ", formattedKey=" + formattedKey + ", count=" + count - + ", subAggregationResult=" + Arrays.toString(subAggregationResult) + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java deleted file mode 100644 index 923afbf..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResult.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Arrays; - -public class AggregationResult { - private String name; - - private Number count; - - private AggregationBucket[] buckets; - - @JsonProperty("nested-aggregations") - private AggregationResult[] nestedAggregations; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public AggregationBucket[] getBuckets() { - return buckets; - } - - public void setBuckets(AggregationBucket[] buckets) { - this.buckets = buckets; - } - - public AggregationResult[] getNestedAggregations() { - return nestedAggregations; - } - - public void setNestedAggregations(AggregationResult[] nestedAggregations) { - this.nestedAggregations = nestedAggregations; - } - - public Number getCount() { - return count; - } - - public void setCount(Number count) { - this.count = count; - } - - @Override - public String toString() { - return "AggregationResult [name=" + name + ", count=" + count + ", buckets=" + Arrays.toString(buckets) - + ", nestedAggregations=" + Arrays.toString(nestedAggregations) + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java deleted file mode 100644 index f8f3ed3..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/AggregationResults.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import java.util.Arrays; - -public class AggregationResults { - private AggregationResult[] aggregations; - - public AggregationResult[] getAggregations() { - return aggregations; - } - - public void setAggregations(AggregationResult[] aggregations) { - this.aggregations = aggregations; - } - - @Override - public String toString() { - return "AggregationResults [aggregations=" + Arrays.toString(aggregations) + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java deleted file mode 100644 index 8b7df43..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/Document.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import org.json.simple.JSONObject; - -public class Document { - private String etag; - private String url; - - private JSONObject content; - - public String getEtag() { - return etag; - } - - public void setEtag(String etag) { - this.etag = etag; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public String toString() { - return "Document [etag=" + etag + ", url=" + url + "]"; - } - - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java deleted file mode 100644 index 9775446..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/DocumentOperationResult.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class DocumentOperationResult extends OperationResult { - private Document document; - - public Document getDocument() { - return document; - } - - public void setDocument(Document document) { - this.document = document; - } - - @Override - public String toString() { - return "DocumentOperationResult [document=" + document + "]"; - } - - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java deleted file mode 100644 index aa7e720..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/ErrorResult.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class ErrorResult { - - private String type; - private String reason; - - public ErrorResult(String type, String reason) { - super(); - this.type = type; - this.reason = reason; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - @Override - public String toString() { - return "ErrorResponse [type=" + type + ", reason=" + reason + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java deleted file mode 100644 index 0d3a8bb..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResult.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class OperationResult { - - private int resultCode; - - private String failureCause; - private String resultVersion; - private String result; - private ErrorResult error; - - public int getResultCode() { - return resultCode; - } - - public void setResultCode(int resultCode) { - this.resultCode = resultCode; - } - - public String getFailureCause() { - return failureCause; - } - - public void setFailureCause(String failureCause) { - this.failureCause = failureCause; - } - - public String getResultVersion() { - return resultVersion; - } - - public void setResultVersion(String resultVersion) { - this.resultVersion = resultVersion; - } - - public String getResult() { - return result; - } - - public void setResult(String result) { - this.result = result; - } - - public ErrorResult getError() { - return error; - } - - public void setError(ErrorResult error) { - this.error = error; - } - - @Override - public String toString() { - return "OperationResult [resultCode=" + resultCode + ", failureCause=" + failureCause + ", resultVersion=" - + resultVersion + ", result=" + result + ", error=" + error + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java deleted file mode 100644 index 32b1d0c..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/OperationResultBuilder.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ - -package org.onap.aai.sa.searchdbabstraction.entity; - -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - -public class OperationResultBuilder { - - public enum Type { - DOCUMENT, - SEARCH - } - - private static final String INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT = - "Internal Error: ElasticSearch operation fault occurred"; - - private OperationResult opResult; - - public OperationResultBuilder() { - opResult = new OperationResult(); - } - - public OperationResultBuilder(Type type) { - switch (type) { - case DOCUMENT: - opResult = new DocumentOperationResult(); - break; - case SEARCH: - opResult = new SearchOperationResult(); - break; - default: - opResult = new OperationResult(); - } - } - - public OperationResult build() { - return opResult; - } - - public OperationResultBuilder useDefaults() { - opResult.setResultCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); - opResult.setResult(INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT); - return this; - } - - public OperationResultBuilder resultCode(int resultCode) { - opResult.setResultCode(resultCode); - return this; - } - - public OperationResultBuilder status(Status status) { - return resultCode(status.getStatusCode()); - } - - public OperationResultBuilder failureCause(String failureCause) { - opResult.setFailureCause(failureCause); - return this; - } - - public OperationResultBuilder result(String resultMsg) { - opResult.setResult(resultMsg); - return this; - } - - public OperationResultBuilder resultVersion(String resultVersion) { - opResult.setResultVersion(resultVersion); - return this; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java deleted file mode 100644 index 033dafe..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHit.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class SearchHit { - private String score; - Document document; - - public String getScore() { - return score; - } - - public void setScore(String score) { - this.score = score; - } - - public Document getDocument() { - return document; - } - - public void setDocument(Document document) { - this.document = document; - } - - @Override - public String toString() { - return "SearchHit [score=" + score + ", document=" + document + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java deleted file mode 100644 index cf4fd3a..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchHits.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import java.util.Arrays; - -public class SearchHits { - private String totalHits; - private SearchHit[] hits; - - public String getTotalHits() { - return totalHits; - } - - public void setTotalHits(String totalHits) { - this.totalHits = totalHits; - } - - public SearchHit[] getHits() { - return hits; - } - - public void setHits(SearchHit[] hits) { - this.hits = hits; - } - - @Override - public String toString() { - return "SearchHits [totalHits=" + totalHits + ", hits=" + Arrays.toString(hits) + "]"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java deleted file mode 100644 index 6834d33..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SearchOperationResult.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class SearchOperationResult extends OperationResult { - - private SearchHits searchResult; - private AggregationResults aggregationResult; - private SuggestHits suggestResult; - - public SearchHits getSearchResult() { - return searchResult; - } - - public SuggestHits getSuggestResult() { - return suggestResult; - } - - public AggregationResults getAggregationResult() { - return aggregationResult; - } - - public void setAggregationResult(AggregationResults aggregations) { - this.aggregationResult = aggregations; - } - - public void setSearchResult(SearchHits hits) { - this.searchResult = hits; - } - - public void setSuggestResult(SuggestHits hits) { - this.suggestResult = hits; - } - - @Override - public String toString() { - return "SearchOperationResult [searchResult=" + searchResult + ", aggregationResult=" + aggregationResult - + ", suggestResult=" + suggestResult; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java deleted file mode 100644 index 4ce267d..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHit.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -public class SuggestHit { - - private String score; - private String text; - Document document; - - public String getScore() { - return score; - } - - public void setScore(String score) { - this.score = score; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public Document getDocument() { - return document; - } - - public void setDocument(Document document) { - this.document = document; - } - - @Override - public String toString() { - return "SearchHit [text=" + text + ",score=" + score + ", document=" + document + "]"; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java deleted file mode 100644 index ecc4f25..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/entity/SuggestHits.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.entity; - -import java.util.Arrays; - -public class SuggestHits { - - private String totalHits; - private SuggestHit[] hits; - - public String getTotalHits() { - return totalHits; - } - - public void setTotalHits(String totalHits) { - this.totalHits = totalHits; - } - - public SuggestHit[] getHits() { - return hits; - } - - public void setHits(SuggestHit[] hits) { - this.hits = hits; - } - - @Override - public String toString() { - return "SuggestHit [totalHits=" + totalHits + ", hits=" + Arrays.toString(hits) + "]"; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java deleted file mode 100644 index d38de2a..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/logging/SearchDbMsgs.java +++ /dev/null @@ -1,182 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.logging; - -import com.att.eelf.i18n.EELFResourceManager; -import org.onap.aai.cl.eelf.LogMessageEnum; - -public enum SearchDbMsgs implements LogMessageEnum { - - /** - * Arguments: None - */ - SERVICE_STARTED, - - /** - * Arguments: {0} = url - */ - ELASTIC_SEARCH_CONNECTION_ATTEMPT, - - /** - * Arguments: {0} = url - */ - ELASTIC_SEARCH_CONNECTION_SUCCESS, - - /** - * Arguments: {0} = url {1} = failure cause - */ - ELASTIC_SEARCH_CONNECTION_FAILURE, - - /** - * Arguments: {0} = Filter configuration file. {1} = Failure cause. - */ - FILTERS_CONFIG_FAILURE, - - /** - * Arguments: {0} = Analysys configuration file. {1} = Failure case. - */ - ANALYSYS_CONFIG_FAILURE, - - /** - * Arguments: {0} = Index name - */ - CREATED_INDEX, - - /** - * Arguments: {0} = Index name {1} = Document type - */ - CREATE_INDEX_TIME, - - /** - * Arguments: {0} = Index name - */ - DELETED_INDEX, - - /** - * Arguments: {0} = Index name - */ - DELETE_INDEX_TIME, - - /** - * Arguments: {0} = Index name - */ - CHECK_INDEX_TIME, - - /** - * Arguments: {0} = Index name - */ - CREATE_DOCUMENT_TIME, - - /** - * Arguments: {0} = Index name {1} = Document id - */ - UPDATE_DOCUMENT_TIME, - - /** - * Arguments: {0} = Index name {1} = Document id - */ - DELETE_DOCUMENT_TIME, - - /** - * Arguments: {0} = Index name {1} = Document id - */ - GET_DOCUMENT_TIME, - - /** - * Arguments: {0} = Index name {1} = Query string - */ - QUERY_DOCUMENT_TIME, - - /** - * Arguments: - */ - BULK_OPERATIONS_TIME, - - /** - * Arguments: - */ - PROCESSED_BULK_OPERATIONS, - - /** - * Arguments: {0} = Event {1} = Result - */ - PROCESS_EVENT, - - /** - * Arguments: {0} = URL. - */ - PROCESS_INLINE_QUERY, - - /** - * Arguments {0} - Operation type (GET or POST) {1} - URL. - */ - PROCESS_PAYLOAD_QUERY, - - /** - * Arguments: {0} = Index {1} = Error - */ - INDEX_CREATE_FAILURE, - - /** - * Arguments: {0} = Index name {1} = Error cause - */ - INDEX_DELETE_FAILURE, - - /** - * Arguments: {0} = Failure cause. - */ - GET_ANALYZERS_FAILURE, - - /** - * Arguments: {0} = Failure cause. - */ - BULK_OPERATION_FAILURE, - - /** - * Arguments: {0} = Method {1} = Exception - */ - EXCEPTION_DURING_METHOD_CALL, - - /** - * Received request {0} {1} from {2}. Sending response: {3} - * - *

- * Arguments: {0} = operation {1} = target URL {2} = source {3} = response code - */ - PROCESS_REST_REQUEST, - - STARTUP_EXCEPTION - /** - * Exception encountered during startup of search service: {0} - * - *

- * Arguments: {0} = exception - */ - ; - - /** - * Load message bundle (SearchDbMsgs.properties file) - */ - static { - EELFResourceManager.loadMessageBundle("logging/SearchDbMsgs"); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java deleted file mode 100644 index 29be5ea..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AbstractAggregation.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * This is the common parent from which all aggregation types inherit. It defines the common fields that all - * aggregations must include. - */ -public abstract class AbstractAggregation { - - /** - * The name of the field to apply the aggregation against. - */ - protected String field; - - /** - * Optionally allows the number of buckets for the aggregation to be specified. - */ - protected Integer size; - - /** - * Optionally sets the minimum number of matches that must occur before a particular bucket is included in the - * aggregation result. - */ - @JsonProperty("min-threshold") - protected Integer minThreshold; - - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public Integer getSize() { - return size; - } - - public void setSize(Integer size) { - this.size = size; - } - - public Integer getMinThreshold() { - return minThreshold; - } - - public void setMinThreshold(Integer minThreshold) { - this.minThreshold = minThreshold; - } - - public abstract String toElasticSearch(); - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java deleted file mode 100644 index 84f0e9e..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class Aggregation { - private String name; - - @JsonProperty("aggregation") - private AggregationStatement aggregation; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public AggregationStatement getStatement() { - return aggregation; - } - - public void setStatement(AggregationStatement aggregation) { - this.aggregation = aggregation; - } - - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - sb.append("\""); - sb.append(name); - sb.append("\": "); - sb.append(aggregation.toElasticSearch()); - return sb.toString(); - } - - @Override - public String toString() { - return "{name: " + name + ", aggregation: " + aggregation.toString(); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java deleted file mode 100644 index 94a091d..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Arrays; - -public class AggregationStatement { - - @JsonProperty("group-by") - private GroupByAggregation groupBy; - - @JsonProperty("date-range") - private DateRangeAggregation dateRange; - - @JsonProperty("date-histogram") - private DateHistogramAggregation dateHist; - - @JsonProperty("nested") - private Aggregation[] nested; - - @JsonProperty("sub-aggregations") - private Aggregation[] subAggregations; - - public GroupByAggregation getGroupBy() { - return groupBy; - } - - public void setGroupBy(GroupByAggregation groupBy) { - this.groupBy = groupBy; - } - - public DateRangeAggregation getDateRange() { - return dateRange; - } - - public void setDateRange(DateRangeAggregation dateRange) { - this.dateRange = dateRange; - } - - public DateHistogramAggregation getDateHist() { - return dateHist; - } - - public void setDateHist(DateHistogramAggregation dateHist) { - this.dateHist = dateHist; - } - - public Aggregation[] getNested() { - return nested; - } - - public void setNested(Aggregation[] nested) { - this.nested = nested; - } - - public Aggregation[] getSubAggregations() { - return subAggregations; - } - - public void setSubAggregations(Aggregation[] subAggregations) { - this.subAggregations = subAggregations; - } - - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - if (nested != null && nested.length > 0) { - sb.append("\"nested\": {\"path\": \""); - if (nested[0].getStatement() != null) { - sb.append(nested[0].getStatement().getNestedPath()); - } - sb.append("\"}, \"aggs\": {"); - for (int i = 0; i < nested.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(nested[i].toElasticSearch()); - } - - sb.append("}"); - } else { - if (groupBy != null) { - sb.append(groupBy.toElasticSearch()); - } else if (dateRange != null) { - sb.append(dateRange.toElasticSearch()); - } else if (dateHist != null) { - sb.append(dateHist.toElasticSearch()); - } - - if (subAggregations != null && subAggregations.length > 0) { - sb.append(", \"aggs\": {"); - for (int i = 0; i < subAggregations.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(subAggregations[i].toElasticSearch()); - } - sb.append("}"); - } - } - - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - if (nested != null) { - sb.append("{nested: "); - sb.append(Arrays.toString(nested)); - } else if (groupBy != null) { - sb.append(groupBy.toString()); - } else if (dateHist != null) { - sb.append(dateHist.toString()); - } else if (dateRange != null) { - sb.append(dateRange.toString()); - } - - if (subAggregations != null) { - sb.append(", sub-aggregations: "); - sb.append(Arrays.toString(subAggregations)); - } - - sb.append("}"); - - return sb.toString(); - } - - public String getNestedPath() { - String path = null; - String fieldName = null; - - if (groupBy != null) { - fieldName = groupBy.getField(); - } else if (dateRange != null) { - fieldName = dateRange.getField(); - } else if (dateHist != null) { - fieldName = dateHist.getField(); - } - - if (fieldName != null && fieldName.contains(".")) { - // we have nested field - path = fieldName.substring(0, fieldName.indexOf(".")); - } - - return path; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java deleted file mode 100644 index 96bb25d..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregation.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An example of elasticsearch date_histogram aggregation: - * - *

- * - *

- * {
- *    "aggs": {
- *        "my_group": {
- *            "date_histogram" : {
- *               "field" : "date",
- *               "interval" : "month"
- *           }
- *        }
- *    }
- * }
- * 
- */ - -public class DateHistogramAggregation extends AbstractAggregation { - - private String interval; - - private String format; - - @JsonProperty("time-zone") - private String timeZone; - - - public String getInterval() { - return interval; - } - - public void setInterval(String interval) { - this.interval = interval; - } - - public String getTimeZone() { - return timeZone; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public void setTimeZone(String timeZone) { - this.timeZone = timeZone; - } - - @Override - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - - sb.append("\"date_histogram\": {\"field\": \""); - sb.append(field); - sb.append("\""); - if (interval != null) { - sb.append(", \"interval\": \""); - sb.append(interval); - sb.append("\""); - } - if (format != null) { - sb.append(", \"format\": \""); - sb.append(format); - sb.append("\""); - } - if (timeZone != null) { - sb.append(", \"time_zone\": \""); - sb.append(timeZone); - sb.append("\""); - } - if (size != null) { - sb.append(", \"size\": "); - sb.append(size); - } - if (minThreshold != null) { - sb.append(", \"min_doc_count\": ").append(minThreshold); - } - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - return "DateHistogramAggregation: [field=" + field + ", interval=" + interval + ", format=" + format - + ", timeZone=" + timeZone + ", size=" + size + " minThreshold=" + minThreshold; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java deleted file mode 100644 index cd49ee7..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRange.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * This class represents the ranges specification in an date_range statement. - *

- * The expected JSON structure for a ranges is as follows: - *

- * - *

- * {
- *  "from": 
- * }
- * 
- *

- * or - *

- * - *

- * {
- *  "to": 
- * }
- * 
- *

- * or - *

- * - *

- * {
- *  "from": ,
- *  "to": 
- * }
- * 
- * - * @author sye - */ -public class DateRange { - - @JsonProperty("from") - private String fromDate; - - @JsonProperty("to") - private String toDate; - - public String getFromDate() { - return fromDate; - } - - public void setFromDate(String fromDate) { - this.fromDate = fromDate; - } - - public String getToDate() { - return toDate; - } - - public void setToDate(String toDate) { - this.toDate = toDate; - } - - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - if (fromDate != null) { - sb.append("\"from\": \""); - sb.append(fromDate); - sb.append("\""); - } - - if (toDate != null) { - if (fromDate != null) { - sb.append(", \"to\": \""); - sb.append(toDate); - sb.append("\""); - } else { - sb.append("\"to\": \""); - sb.append(toDate); - sb.append("\""); - } - } - - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - return "{from: " + fromDate + ", to: " + toDate + "}"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java deleted file mode 100644 index a4e0cc2..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An example of a date_range aggregation: - * - *

- * - *

- * {
- *    "aggs": {
- *        "range": {
- *            "date_range": {
- *                "field": "date",
- *                "format": "MM-yyy",
- *                "ranges": [
- *                    { "to": "now-10M/M" },
- *                    { "from": "now-10M/M" }
- *                ]
- *            }
- *        }
- *    }
- * }
- * 
- * - * @author sye - */ -public class DateRangeAggregation extends AbstractAggregation { - - private String format; - - @JsonProperty("ranges") - private DateRange[] dateRanges; - - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public DateRange[] getDateRanges() { - return dateRanges; - } - - public void setDateRanges(DateRange[] dateRanges) { - this.dateRanges = dateRanges; - } - - @Override - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - - sb.append("\"date_range\": {\"field\": \""); - sb.append(field); - sb.append("\""); - - if (format != null) { - sb.append(", \"format\": \""); - sb.append(format); - sb.append("\""); - } - - if (dateRanges != null && dateRanges.length > 0) { - sb.append(", \"ranges\": ["); - - for (int i = 0; i < dateRanges.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(dateRanges[i].toElasticSearch()); - } - - sb.append("]"); - } - - if (size != null) { - sb.append(", \"size\": "); - sb.append(size); - } - - if (minThreshold != null) { - sb.append(", \"min_doc_count\": ").append(minThreshold); - } - - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("date-range: {field: " + field + ", format: " + format + ", size: " + size + ", minThreshold: " - + minThreshold + "ranges: ["); - for (int i = 0; i < dateRanges.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(dateRanges[i].toString()); - } - sb.append("]"); - - return sb.toString(); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java deleted file mode 100644 index 134c660..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java +++ /dev/null @@ -1,183 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import java.util.ArrayList; -import java.util.List; - -/** - * This class represents the filter stanza in a search statement. - * - *

- * The expected JSON structure for a filter stanza is as follows: - * - *

- * {
- *     "filter": {
- *        "all": [ {query structure}, {query structure}, ... {query structure} ],
- *        "any": [ {query structure}, {query structure}, ... {query structure} ]
- *     }
- * }
- * 
- */ -public class Filter { - - /** - * All queries in this list must evaluate to true for the filter to pass. - */ - private QueryStatement[] all; - - /** - * Any one of the queries in this list must evaluate to true for the filter to pass. - */ - private QueryStatement[] any; - - - public QueryStatement[] getAll() { - return all; - } - - public void setAll(QueryStatement[] all) { - this.all = all; - } - - public QueryStatement[] getAny() { - return any; - } - - public void setAny(QueryStatement[] any) { - this.any = any; - } - - /** - * This method returns a string which represents this filter in syntax that is understandable by ElasticSearch and - * is suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - List notMatchQueries = new ArrayList<>(); - sb.append("{"); - sb.append("\"bool\": {"); - - // Add the queries from our 'all' list. - int matchQueriesCount = 0; - int notMatchQueriesCount = 0; - if (all != null) { - sb.append("\"must\": ["); - - for (QueryStatement query : all) { - if (matchQueriesCount > 0) { - sb.append(", "); - } - - if (query.isNotMatch()) { - notMatchQueries.add(query); - } else { - sb.append(query.toElasticSearch()); - matchQueriesCount++; - } - } - sb.append("],"); - - - sb.append("\"must_not\": ["); - for (QueryStatement query : notMatchQueries) { - if (notMatchQueriesCount > 0) { - sb.append(", "); - } - sb.append(query.toElasticSearch()); - notMatchQueriesCount++; - } - sb.append("]"); - } - - // Add the queries from our 'any' list. - notMatchQueries.clear(); - if (any != null) { - if (all != null) { - sb.append(","); - } - sb.append("\"should\": ["); - - matchQueriesCount = 0; - for (QueryStatement query : any) { - if (matchQueriesCount > 0) { - sb.append(", "); - } - - if (query.isNotMatch()) { - notMatchQueries.add(query); - } else { - sb.append(query.toElasticSearch()); - matchQueriesCount++; - } - } - sb.append("],"); - - notMatchQueriesCount = 0; - sb.append("\"must_not\": ["); - for (QueryStatement query : notMatchQueries) { - if (notMatchQueriesCount > 0) { - sb.append(", "); - } - sb.append(query.toElasticSearch()); - notMatchQueriesCount++; - } - sb.append("]"); - } - sb.append("}"); - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - sb.append("all: ["); - if (all != null) { - for (QueryStatement query : all) { - sb.append(query.toString()); - } - } - sb.append("], "); - - sb.append("any: ["); - if (any != null) { - for (QueryStatement query : any) { - sb.append(query.toString()); - } - } - sb.append("] "); - - sb.append("}"); - - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java deleted file mode 100644 index 69730d2..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregation.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -/** - * An example of a date_range aggregation: - * - *

- * - *

- * {
- *    "aggs": {
- *        "my_group": {
- *            "term": {
- *                "field": "group"
- *            }
- *        }
- *    }
- * }
- * 
- * - * @author sye - */ -public class GroupByAggregation extends AbstractAggregation { - - @Override - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - - sb.append("\"terms\": {\"field\": \""); - sb.append(field); - sb.append("\""); - if (size != null) { - sb.append(", \"size\": "); - sb.append(size); - } - - if (minThreshold != null) { - sb.append(", \"min_doc_count\": ").append(minThreshold); - } - - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - return "{group-by: {field: " + field + ", size: " + size + " minThreshold: " + minThreshold + "}}"; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java deleted file mode 100644 index 19bc250..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/ParsedQuery.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * This class represents a simple parsed query statement. - * - *

- * A 'parsed query' specifies a document field to inspect and a query string which will be parsed by the document store - * to generate the exact query to be performed. - * - *

- * The query string will be tokenized into 'terms' and 'operators' where: - * - *

- * Terms may be any of the following: - *

    - *
  • single words
  • - *
  • exact phrases (denoted by surrounding the phrase with '"' characters)
  • - *
  • regular expressions (denoted by surrounding the phrase with '/' characters)
  • - *
- * - *

- * Operators may be any of the following: - *

    - *
  • + -- The term to the right of the operator MUST be present to produce a match.
  • - *
  • - -- The term to the right of the operator MUST NOT be present to produce a match.
  • - *
  • AND -- Both the terms to the left and right of the operator MUST be present to produce a match.
  • - *
  • OR -- Either the term to the left or right of the operator MUST be present to produce a match.
  • - *
  • NOT -- The term to the right of the operator MUST NOT be present to produce a match.
  • - *
- * - *

- * The expected JSON structure for a parsed query is as follows: - * - *

- *     {
- *         "parsed-query": {
- *             "field": "fieldname",
- *             "query-string": "string"
- *         }
- *     }
- * 
- */ -public class ParsedQuery { - - /** - * The name of the field which the query is to be applied to. - */ - private String field; - - /** - * The string to be parsed to generate the full query. - */ - @JsonProperty("query-string") - private String queryString; - - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public String getQueryString() { - return queryString; - } - - public void setQueryString(String queryString) { - this.queryString = queryString; - } - - - /** - * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is - * suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - sb.append("\"query_string\": {"); - sb.append("\"default_field\": \"").append(field).append("\", "); - sb.append("\"query\": \"").append(queryString).append("\""); - sb.append("}"); - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - return "{field:" + field + ", query-string: '" + queryString + "'}"; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java deleted file mode 100644 index ee8ffdc..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Query.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -public class Query { - - private QueryStatement may; - private QueryStatement must; - - public QueryStatement getMay() { - return may; - } - - public void setMay(QueryStatement may) { - this.may = may; - } - - public QueryStatement getMust() { - return must; - } - - public void setMust(QueryStatement must) { - this.must = must; - } - - public QueryStatement getQueryStatement() { - if (isMust()) { - return must; - } else if (isMay()) { - return may; - } else { - return null; - } - } - - public boolean isMust() { - return must != null; - } - - public boolean isMay() { - return may != null; - } - - public String toElasticSearch() { - - if (isMust()) { - return must.toElasticSearch(); - } else if (isMay()) { - return may.toElasticSearch(); - } else { - return ""; // throw an exception? - } - } - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append("Query:["); - if (isMust()) { - sb.append("must: ").append(must.toString()); - } else if (isMay()) { - sb.append("may: ").append(may.toString()); - } else { - sb.append("INVALID"); - } - sb.append("]"); - - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java deleted file mode 100644 index 7764051..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryStatement.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class QueryStatement { - - private TermQuery match; - - @JsonProperty("not-match") - private TermQuery notMatch; - - @JsonProperty("parsed-query") - private ParsedQuery parsedQuery; - - private RangeQuery range; - - public TermQuery getMatch() { - return match; - } - - public void setMatch(TermQuery match) { - this.match = match; - } - - public TermQuery getNotMatch() { - return notMatch; - } - - public void setNotMatch(TermQuery notMatch) { - this.notMatch = notMatch; - } - - public ParsedQuery getParsedQuery() { - return parsedQuery; - } - - public void setParsedQuery(ParsedQuery parsedQuery) { - this.parsedQuery = parsedQuery; - } - - public RangeQuery getRange() { - return range; - } - - public void setRange(RangeQuery range) { - this.range = range; - } - - public boolean isNotMatch() { - return (notMatch != null); - } - - public String toElasticSearch() { - - if (match != null) { - return match.toElasticSearch(); - - } else if (notMatch != null) { - return notMatch.toElasticSearch(); - - } else if (parsedQuery != null) { - - // We need some special wrapping if this query is against a nested field. - if (fieldIsNested(parsedQuery.getField())) { - return "{\"nested\": { \"path\": \"" + pathForNestedField(parsedQuery.getField()) + "\", \"query\": " - + parsedQuery.toElasticSearch() + "}}"; - } else { - return parsedQuery.toElasticSearch(); - } - - } else if (range != null) { - - // We need some special wrapping if this query is against a nested field. - if (fieldIsNested(range.getField())) { - return "{\"nested\": { \"path\": \"" + pathForNestedField(range.getField()) + "\", \"query\": " - + range.toElasticSearch() + "}}"; - } else { - return range.toElasticSearch(); - } - - } else { - // throw an exception? - return null; - } - } - - private boolean fieldIsNested(String field) { - return field.contains("."); - } - - private String pathForNestedField(String field) { - int index = field.lastIndexOf('.'); - return field.substring(0, index); - } - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - if (match != null) { - sb.append("TERM QUERY: { match: {").append(match.toString()).append("}}"); - } else if (notMatch != null) { - sb.append("TERM QUERY: { not-match: {").append(match.toString()).append("}}"); - } else if (parsedQuery != null) { - sb.append("PARSED QUERY: { ").append(parsedQuery.toString()).append("}"); - } else if (range != null) { - sb.append("RANGE QUERY: { ").append(range.toString()).append("}"); - } else { - sb.append("UNDEFINED"); - } - - sb.append("}"); - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java deleted file mode 100644 index 60cc9e6..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQuery.java +++ /dev/null @@ -1,336 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * This class represents a simple range query. - * - *

- * A range query is composed of one or more operator/value pairs which define the upper and lower bounds of the range, - * and a field to apply the query to. - * - *

- * Operators may be one of the following: - *

    - *
  • gt - Greater than.
  • - *
  • gte - Greater than or equal to.
  • - *
  • lt - Less than.
  • - *
  • lte - Less than or equal to.
  • - *
- * Values may be either numeric values (Integer or Double) or Strings representing dates. - * - *

- * The following examples illustrate a couple of variants of the range query: - * - *

- * - *

- *     // A simple numeric range query:
- *     {
- *         "range": {
- *             "field": "fieldname",
- *             "gte": 5,
- *             "lte": 10
- *         }
- *     }
- *
- *     // A simple date range query:
- *     {
- *         "range": {
- *             "field": "fieldname",
- *             "gt": "2016-10-06T00:00:00.558+03:00",
- *             "lt": "2016-10-06T23:59:59.558+03:00"
- *         }
- *     }
- * 
- */ -public class RangeQuery { - - /** - * The name of the field to apply the range query against. - */ - private String field; - - /** - * The value of the field must be greater than this value to be a match.
- * NOTE: Only one of 'gt' or 'gte' should be set on any single {@link RangeQuery} instance. - */ - private Object gt; - - /** - * The value of the field must be greater than or equal to this value to be a match.
- * NOTE: Only one of 'gt' or 'gte' should be set on any single {@link RangeQuery} instance. - */ - private Object gte; - - /** - * The value of the field must be less than this value to be a match.
- * NOTE: Only one of 'lt' or 'lte' should be set on any single {@link RangeQuery} instance. - */ - private Object lt; - - /** - * The value of the field must be less than or equal to than this value to be a match.
- * NOTE: Only one of 'lt' or 'lte' should be set on any single {@link RangeQuery} instance. - */ - private Object lte; - - private String format; - - @JsonProperty("time-zone") - private String timeZone; - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public Object getGt() { - return gt; - } - - public void setGt(Object gt) { - - // It does not make sense to assign a value to both the 'greater than' - // and 'greater than or equal' operations, so make sure we are not - // trying to do that. - if (gte == null) { - - // Make sure that we are not trying to mix both numeric and date - // type values in the same queries. - if (((lt != null) && !typesMatch(gt, lt)) || ((lte != null) && !typesMatch(gt, lte))) { - throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); - } - - // If we made it here, then we're all good. Store the value. - this.gt = gt; - } else { - throw new IllegalArgumentException("Cannot assign both 'gt' and 'gte' fields in the same ranged query"); - } - } - - - public Object getGte() { - return gte; - } - - public void setGte(Object gte) { - - // It does not make sense to assign a value to both the 'greater than' - // and 'greater than or equal' operations, so make sure we are not - // trying to do that. - if (gt == null) { - - // Make sure that we are not trying to mix both numeric and date - // type values in the same queries. - if (((lt != null) && !typesMatch(gte, lt)) || ((lte != null) && !typesMatch(gte, lte))) { - throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); - } - - // If we made it here, then we're all good. Store the value. - this.gte = gte; - - } else { - throw new IllegalArgumentException("Cannot assign both 'gt' and 'gte' fields in the same ranged query"); - } - } - - public Object getLt() { - return lt; - } - - public void setLt(Object lt) { - - // It does not make sense to assign a value to both the 'less than' - // and 'less than or equal' operations, so make sure we are not - // trying to do that. - if (lte == null) { - - // Make sure that we are not trying to mix both numeric and date - // type values in the same queries. - if (((gt != null) && !typesMatch(lt, gt)) || ((gte != null) && !typesMatch(lt, gte))) { - throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); - } - - // If we made it here, then we're all good. Store the value. - - this.lt = lt; - } else { - throw new IllegalArgumentException("Cannot assign both 'lt' and 'lte' fields in the same ranged query"); - } - } - - public Object getLte() { - return lte; - } - - public void setLte(Object lte) { - - // It does not make sense to assign a value to both the 'greater than' - // and 'greater than or equal' operations, so make sure we are not - // trying to do that. - if (lt == null) { - - // Make sure that we are not trying to mix both numeric and date - // type values in the same queries. - if (((gt != null) && !typesMatch(lte, gt)) || ((gte != null) && !typesMatch(lte, gte))) { - throw new IllegalArgumentException("Cannot mix date and numeric values in the same ranged query"); - } - - // If we made it here, then we're all good. Store the value. - - this.lte = lte; - } else { - throw new IllegalArgumentException("Cannot assign both 'lt' and 'lte' fields in the same ranged query"); - } - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public String getTimeZone() { - return timeZone; - } - - public void setTimeZone(String timeZone) { - this.timeZone = timeZone; - } - - /** - * This convenience method determines whether or not the supplied value needs to be enclosed in '"' characters when - * generating ElasticSearch compatible syntax. - * - * @param val - The value to check. - * @return - A string representation of the value for inclusion in an ElasticSearch syntax string. - */ - private String formatStringOrNumericVal(Object val) { - - if (val instanceof String) { - return "\"" + val.toString() + "\""; - } else { - return val.toString(); - } - } - - - /** - * This convenience method verifies that the supplied objects are of classes considered to be compatible for a - * ranged query. - * - * @param value1 - The first value to check. - * @param value2 - The second value to check. - * @return - True if the two objects are compatible for inclusion in the same ranged query, False, otherwise. - */ - boolean typesMatch(Object value1, Object value2) { - - return ((value1 instanceof String) && (value2 instanceof String)) - || (!(value1 instanceof String) && !(value2 instanceof String)); - } - - - /** - * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is - * suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - sb.append("\"range\": {"); - sb.append("\"").append(field).append("\": {"); - - // We may have one or zero of 'greater than' or 'greater - // than or equal' - boolean needComma = false; - if (gte != null) { - sb.append("\"gte\": ").append(formatStringOrNumericVal(gte)); - needComma = true; - } else if (gt != null) { - sb.append("\"gt\": ").append(formatStringOrNumericVal(gt)); - needComma = true; - } - - // We may have one or zero of 'less than' or 'less - // than or equal' - if (lte != null) { - if (needComma) { - sb.append(", "); - } - sb.append("\"lte\": ").append(formatStringOrNumericVal(lte)); - } else if (lt != null) { - if (needComma) { - sb.append(", "); - } - sb.append("\"lt\": ").append(formatStringOrNumericVal(lt)); - } - - // Append the format specifier if one was provided. - if (format != null) { - sb.append(", \"format\": \"").append(format).append("\""); - } - - // Append the time zone specifier if one was provided. - if (timeZone != null) { - sb.append(", \"time_zone\": \"").append(timeZone).append("\""); - } - - sb.append("}"); - sb.append("}"); - sb.append("}"); - - return sb.toString(); - } - - @Override - public String toString() { - - String str = "{ field: " + field + ", "; - - if (gt != null) { - str += "gt: " + gt; - } else if (gte != null) { - str += "gte: " + gte; - } - - if (lt != null) { - str += (((gt != null) || (gte != null)) ? ", " : "") + "lt: " + lt; - } else if (lte != null) { - str += (((gt != null) || (gte != null)) ? ", " : "") + "lte: " + lte; - } - - str += "}"; - - return str; - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java deleted file mode 100644 index d14f8df..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java +++ /dev/null @@ -1,319 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import org.radeox.util.logging.Logger; - -/** - * This class represents the structure of a search statement. - * - *

- * The expected JSON structure to represent a search statement is as follows: - * - *

- * - *

- *     {
- *         "results-start": int,  - Optional: index of starting point in result set.
- *         "results-size": int,   - Optional: maximum number of documents to include in result set.
- *
- *         "filter": {
- *             { filter structure - see {@link Filter} }
- *         },
- *
- *         "queries": [
- *             { query structure - see {@link QueryStatement} },
- *             { query structure - see {@link QueryStatement} },
- *                              .
- *                              .
- *             { query structure - see {@link QueryStatement} },
- *         ],
- *
- *         "aggregations": [
- *             { aggregation structure - see {@link AggregationStatement} },
- *             { aggregation structure - see {@link AggregationStatement} },
- *                              .
- *                              .
- *             { aggregation structure - see {@link AggregationStatement} },
- *         ]
- *     }
- * 
- */ -public class SearchStatement { - - /** - * Defines the filters that should be applied before running the actual queries. This is optional. - */ - private Filter filter; - - /** - * The list of queries to be applied to the document store. - */ - private Query[] queries; - - /** - * The list of aggregations to be applied to the search - */ - private Aggregation[] aggregations; - - /** - * Defines the sort criteria to apply to the query result set. This is optional. - */ - private Sort sort; - - @JsonProperty("results-start") - private Integer resultsStart; - - @JsonProperty("results-size") - private Integer size; - - public Filter getFilter() { - return filter; - } - - public void setFilter(Filter filter) { - this.filter = filter; - } - - public Query[] getQueries() { - return queries; - } - - public void setQueries(Query[] queries) { - this.queries = queries; - } - - public Sort getSort() { - return sort; - } - - public void setSort(Sort sort) { - this.sort = sort; - } - - public boolean isFiltered() { - return filter != null; - } - - public Aggregation[] getAggregations() { - return aggregations; - } - - public void setAggregations(Aggregation[] aggregations) { - this.aggregations = aggregations; - } - - public boolean hasAggregations() { - return aggregations != null && aggregations.length > 0; - } - - public Integer getFrom() { - return resultsStart; - } - - public void setFrom(Integer from) { - this.resultsStart = from; - } - - public Integer getSize() { - return size; - } - - public void setSize(Integer size) { - this.size = size; - } - - /** - * This method returns a string which represents this statement in syntax that is understandable by ElasticSearch - * and is suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - List notMatchQueries = new ArrayList<>(); - List mustQueries = new ArrayList<>(); - List shouldQueries = new ArrayList<>(); - - createQueryLists(queries, mustQueries, shouldQueries, notMatchQueries); - - sb.append("{"); - - sb.append("\"version\": true,"); - - // If the client has specified an index into the results for the first - // document in the result set then include that in the ElasticSearch - // query. - if (resultsStart != null) { - sb.append("\"from\": ").append(resultsStart).append(", "); - } - - // If the client has specified a maximum number of documents to be returned - // in the result set then include that in the ElasticSearch query. - if (size != null) { - sb.append("\"size\": ").append(size).append(", "); - } - - sb.append("\"query\": {"); - sb.append("\"bool\": {"); - - sb.append("\"must\": ["); - AtomicBoolean firstQuery = new AtomicBoolean(true); - for (QueryStatement query : mustQueries) { - - if (!firstQuery.compareAndSet(true, false)) { - sb.append(", "); - } - - sb.append(query.toElasticSearch()); - } - sb.append("], "); - - sb.append("\"should\": ["); - - firstQuery = new AtomicBoolean(true); - for (QueryStatement query : shouldQueries) { - - if (!firstQuery.compareAndSet(true, false)) { - sb.append(", "); - } - - sb.append(query.toElasticSearch()); - } - - sb.append("],"); // close should list - - sb.append("\"must_not\": ["); - firstQuery.set(true); - for (QueryStatement query : notMatchQueries) { - sb.append(query.toElasticSearch()); - } - sb.append("]"); - - // Add the filter stanza, if one is required. - if (isFiltered()) { - sb.append(", \"filter\": ").append(filter.toElasticSearch()); - } - - sb.append("}"); // close bool clause - sb.append("}"); // close query clause - - // Add the sort directive, if one is required. - if (sort != null) { - sb.append(", \"sort\": ").append(sort.toElasticSearch()); - } - - // Add aggregations - if (hasAggregations()) { - sb.append(", \"aggs\": {"); - - for (int i = 0; i < aggregations.length; i++) { - if (i > 0) { - sb.append(","); - } - sb.append(aggregations[i].toElasticSearch()); - } - - sb.append("}"); - } - - sb.append("}"); - - Logger.debug("Generated raw ElasticSearch query statement: " + sb.toString()); - return sb.toString(); - } - - private void createQueryLists(Query[] queries, List mustList, List mayList, - List mustNotList) { - - for (Query query : queries) { - - if (query.isMust()) { - - if (query.getQueryStatement().isNotMatch()) { - mustNotList.add(query.getQueryStatement()); - } else { - mustList.add(query.getQueryStatement()); - } - } else { - - if (query.getQueryStatement().isNotMatch()) { - mustNotList.add(query.getQueryStatement()); - } else { - mayList.add(query.getQueryStatement()); - } - } - } - } - - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append("SEARCH STATEMENT: {"); - - if (size != null) { - sb.append("from: ").append(resultsStart).append(", size: ").append(size).append(", "); - } - - if (filter != null) { - sb.append("filter: ").append(filter.toString()).append(", "); - } - - sb.append("queries: ["); - AtomicBoolean firstQuery = new AtomicBoolean(true); - if (queries != null) { - for (Query query : queries) { - - if (!firstQuery.compareAndSet(true, false)) { - sb.append(", "); - } - sb.append(query.toString()); - } - } - sb.append("]"); - - sb.append("aggregations: ["); - firstQuery = new AtomicBoolean(true); - - if (aggregations != null) { - for (Aggregation agg : aggregations) { - - if (!firstQuery.compareAndSet(true, false)) { - sb.append(", "); - } - sb.append(agg.toString()); - } - } - sb.append("]"); - - sb.append("]}"); - - return sb.toString(); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java deleted file mode 100644 index 104c4b0..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Sort.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -public class Sort { - - private String field; - private SortDirection order = null; - - public enum SortDirection { - ascending, - descending - } - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public SortDirection getOrder() { - return order; - } - - public void setOrder(SortDirection order) { - this.order = order; - } - - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{ \"").append(field).append("\": { \"order\": "); - - // If a sort order wasn't explicitly supplied, default to 'ascending'. - if (order != null) { - switch (order) { - case ascending: - sb.append("\"asc\"}}"); - break; - case descending: - sb.append("\"desc\"}}"); - break; - default: - } - } else { - sb.append("\"asc\"}}"); - } - - return sb.toString(); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java deleted file mode 100644 index 2002748..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SuggestionStatement.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; -import org.radeox.util.logging.Logger; - -/** - * This class represents the structure of a search statement. - * - *

- * The expected JSON structure to represent a Completion suggest search statement is as follows: - * - * { "suggest-vnf" : { "text" : "VNFs", "completion" : { "field" : "entity_suggest", "size": 1 } } } - */ -public class SuggestionStatement { - - @JsonProperty("results-size") - private Integer size; - - @JsonProperty("suggest-field") - private String field; - - @JsonProperty("suggest-text") - private String text; - - public Integer getSize() { - return size; - } - - public void setSize(Integer size) { - this.size = size; - } - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - /** - * This method returns a string which represents this statement in syntax that is understandable by ElasticSearch - * and is suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - sb.append("\"suggest-vnf\": {"); - sb.append("\"text\": ").append("\"" + text + "\"").append(", "); - sb.append("\"completion\": {"); - sb.append("\"field\": ").append("\"" + field + "\"").append(", "); - sb.append("\"size\": ").append(size); - sb.append("}"); - sb.append("}"); - sb.append("}"); - - Logger.debug("Generated raw ElasticSearch suggest statement: " + sb.toString()); - return sb.toString(); - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java deleted file mode 100644 index b8afa7e..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQuery.java +++ /dev/null @@ -1,342 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * This class represents a simple term query. - * - *

- * A term query takes an operator, a field to apply the query to and a value to match against the query contents. - * - *

- * Valid operators include: - *

    - *
  • match - Field must contain the supplied value to produce a match.
  • - *
  • not-match - Field must NOT contain the supplied value to produce a match.
  • - *
- * The following examples illustrate the structure of a few variants of the term query: - * - *

- * - *

- *     // Single Field Match Query:
- *     {
- *         "match": {"field": "searchTags", "value": "abcd"}
- *     }
- *
- *     // Single Field Not-Match query:
- *     {
- *         "not-match": {"field": "searchTags", "value": "efgh"}
- *     }
- * 
- * - *

- * - *

- *     // Multi Field Match Query With A Single Value:
- *     {
- *         "match": {"field": "entityType searchTags", "value": "pserver"}
- *     }
- *
- *     // Multi Field Match Query With Multiple Values:
- *     {
- *         "match": {"field": "entityType searchTags", "value": "pserver tenant"}
- *     }
- * 
- */ -public class TermQuery { - - /** - * The name of the field to apply the term query to. - */ - private String field; - - /** - * The value which the field must contain in order to have a match. - */ - private Object value; - - /** - * For multi field queries only. Determines the rules for whether or not a document matches the query, as follows: - * - *

- * "and" - At least one occurrence of every supplied value must be present in any of the supplied fields. - * - *

- * "or" - At least one occurrence of any of the supplied values must be present in any of the supplied fields. - */ - private String operator; - - @JsonProperty("analyzer") - private String searchAnalyzer; - - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - private boolean isNumericValue() { - return ((value instanceof Integer) || (value instanceof Double)); - } - - public String getOperator() { - return operator; - } - - public void setOperator(String operator) { - this.operator = operator; - } - - public String getSearchAnalyzer() { - return searchAnalyzer; - } - - public void setSearchAnalyzer(String searchAnalyzer) { - this.searchAnalyzer = searchAnalyzer; - } - - /** - * This method returns a string which represents this query in syntax that is understandable by ElasticSearch and is - * suitable for inclusion in an ElasticSearch query string. - * - * @return - ElasticSearch syntax string. - */ - public String toElasticSearch() { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - - // Are we generating a multi field query? - if (isMultiFieldQuery()) { - - // For multi field queries, we have to be careful about how we handle - // nested fields, so check to see if any of the specified fields are - // nested. - if (field.contains(".")) { - - // Build the equivalent of a multi match query across one or more nested fields. - toElasticSearchNestedMultiMatchQuery(sb); - - } else { - - // Build a real multi match query, since we don't need to worry about nested fields. - toElasticSearchMultiFieldQuery(sb); - } - } else { - - // Single field query. - - // Add the necessary wrapping if this is a query against a nested field. - if (fieldIsNested(field)) { - sb.append("{\"nested\": { \"path\": \"").append(pathForNestedField(field)).append("\", \"query\": "); - } - - // Build the query. - toElasticSearchSingleFieldQuery(sb); - - if (fieldIsNested(field)) { - sb.append("}}"); - } - } - - sb.append("}"); - - return sb.toString(); - } - - - /** - * Determines whether or not the client has specified a term query with multiple fields. - * - * @return - true if the query is referencing multiple fields, false, otherwise. - */ - private boolean isMultiFieldQuery() { - - return (field.split(" ").length > 1); - } - - - /** - * Constructs a single field term query in ElasticSearch syntax. - * - * @param sb - The string builder to assemble the query string with. - * @return - The single term query. - */ - private void toElasticSearchSingleFieldQuery(StringBuilder sb) { - - sb.append("\"term\": {\"").append(field).append("\" : "); - - // For numeric values, don't enclose the value in quotes. - if (!isNumericValue()) { - sb.append("\"").append(value).append("\""); - } else { - sb.append(value); - } - - sb.append("}"); - } - - - /** - * Constructs a multi field query in ElasticSearch syntax. - * - * @param sb - The string builder to assemble the query string with. - * @return - The multi field query. - */ - private void toElasticSearchMultiFieldQuery(StringBuilder sb) { - - sb.append("\"multi_match\": {"); - - sb.append("\"query\": \"").append(value).append("\", "); - sb.append("\"type\": \"cross_fields\","); - sb.append("\"fields\": ["); - - List fields = Arrays.asList(field.split(" ")); - AtomicBoolean firstField = new AtomicBoolean(true); - for (String f : fields) { - if (!firstField.compareAndSet(true, false)) { - sb.append(", "); - } - sb.append("\"").append(f.trim()).append("\""); - } - sb.append("],"); - - sb.append("\"operator\": \"").append((operator != null) ? operator.toLowerCase() : "and").append("\""); - - if (searchAnalyzer != null) { - sb.append(", \"analyzer\": \"").append(searchAnalyzer).append("\""); - } - - sb.append("}"); - } - - - /** - * Constructs the equivalent of an ElasticSearch multi match query across multiple nested fields. - * - *

- * Since ElasticSearch doesn't really let you do that, we have to be clever and construct an equivalent query using - * boolean operators to produce the same result. - * - * @param sb - The string builder to use to build the query. - */ - public void toElasticSearchNestedMultiMatchQuery(StringBuilder sb) { - - // Break out our whitespace delimited list of fields and values into a actual lists. - List fields = Arrays.asList(field.split(" ")); - List values = Arrays.asList(((String) value).split(" ")); // GDF: revisit this cast. - - sb.append("\"bool\": {"); - - if (operator != null) { - - if (operator.toLowerCase().equals("and")) { - sb.append("\"must\": ["); - } else if (operator.toLowerCase().equals("or")) { - sb.append("\"should\": ["); - } - - } else { - sb.append("\"must\": ["); - } - - AtomicBoolean firstField = new AtomicBoolean(true); - for (String f : fields) { - - if (!firstField.compareAndSet(true, false)) { - sb.append(", "); - } - - sb.append("{ "); - - // Is this a nested field? - if (fieldIsNested(f)) { - - sb.append("\"nested\": {"); - sb.append("\"path\": \"").append(pathForNestedField(f)).append("\", "); - sb.append("\"query\": "); - } - - sb.append("{\"bool\": {"); - sb.append("\"should\": ["); - - AtomicBoolean firstValue = new AtomicBoolean(true); - for (String v : values) { - if (!firstValue.compareAndSet(true, false)) { - sb.append(", "); - } - sb.append("{\"match\": { \""); - sb.append(f).append("\": {\"query\": \"").append(v).append("\""); - - if (searchAnalyzer != null) { - sb.append(", \"analyzer\": \"").append(searchAnalyzer).append("\""); - } - sb.append("}}}"); - } - - sb.append("]"); - sb.append("}"); - - if (fieldIsNested(f)) { - sb.append("}"); - sb.append("}"); - } - - sb.append("}"); - } - - sb.append("]"); - sb.append("}"); - } - - - @Override - public String toString() { - return "field: " + field + ", value: " + value + " (" + value.getClass().getName() + ")"; - } - - public boolean fieldIsNested(String field) { - return field.contains("."); - } - - public String pathForNestedField(String field) { - int index = field.lastIndexOf('.'); - return field.substring(0, index); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java deleted file mode 100644 index 3c4110b..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.service; - -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; -import org.springframework.beans.factory.annotation.Autowired; - -public class SearchService { - static Logger logger = LoggerFactory.getInstance().getLogger(SearchService.class.getName()); - - @Autowired - private ElasticSearchConfig esConfig; - - public SearchService() { - try { - start(); - } catch (Exception e) { - logger.error(SearchDbMsgs.STARTUP_EXCEPTION, e.getLocalizedMessage()); - } - } - - protected void start() throws IOException { - Properties configProperties = new Properties(); - configProperties.load(new FileInputStream(SearchDbConstants.ES_CONFIG_FILE)); - new ElasticSearchHttpController(esConfig); - logger.info(SearchDbMsgs.SERVICE_STARTED); - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java deleted file mode 100644 index b48588f..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/AggregationParsingUtil.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.util; - -import com.fasterxml.jackson.core.JsonProcessingException; -import java.util.Iterator; -import java.util.Set; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationBucket; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; - -public class AggregationParsingUtil { - - private AggregationParsingUtil() { // Do not instantiate - } - - public static AggregationResult[] parseAggregationResults(JSONObject aggregations) throws JsonProcessingException { - - // Obtain the set of aggregation names - Set keySet = aggregations.keySet(); - AggregationResult[] aggResults = new AggregationResult[keySet.size()]; - - int index = 0; - for (Iterator it = keySet.iterator(); it.hasNext();) { - String key = (String) it.next(); - AggregationResult aggResult = new AggregationResult(); - aggResult.setName(key); - - JSONObject bucketsOrNested = (JSONObject) aggregations.get(key); - Object buckets = bucketsOrNested.get("buckets"); - if (buckets == null) { - // we have a nested - Number count = (Number) bucketsOrNested.remove("doc_count"); - aggResult.setCount(count); - AggregationResult[] nestedResults = parseAggregationResults(bucketsOrNested); - aggResult.setNestedAggregations(nestedResults); - } else { - AggregationBucket[] aggBuckets = parseAggregationBuckets((JSONArray) buckets); - aggResult.setBuckets(aggBuckets); - } - - aggResults[index] = aggResult; - index++; - } - - return aggResults; - - } - - private static AggregationBucket[] parseAggregationBuckets(JSONArray buckets) throws JsonProcessingException { - AggregationBucket[] aggBuckets = new AggregationBucket[buckets.size()]; - for (int i = 0; i < buckets.size(); i++) { - AggregationBucket aggBucket = new AggregationBucket(); - JSONObject bucketContent = (JSONObject) buckets.get(i); - Object key = bucketContent.remove("key"); - aggBucket.setKey(key); - Object formatted = bucketContent.remove("key_as_string"); - if (formatted != null) { - aggBucket.setFormattedKey((String) formatted); - } - Object count = bucketContent.remove("doc_count"); - if (count != null) { - aggBucket.setCount((Number) count); - } - bucketContent.remove("from"); - bucketContent.remove("from_as_string"); - bucketContent.remove("to"); - bucketContent.remove("to_as_string"); - - - if (!bucketContent.entrySet().isEmpty()) { - // we have results from sub-aggregation - AggregationResult[] subResult = parseAggregationResults(bucketContent); - if (subResult != null) { - aggBucket.setSubAggregationResult(subResult); - } - } - aggBuckets[i] = aggBucket; - } - - return aggBuckets; - } - -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java deleted file mode 100644 index ebc7ae9..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.util; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.io.IOUtils; -import org.onap.aai.sa.rest.DocumentFieldSchema; -import org.onap.aai.sa.rest.DocumentSchema; - -public class DocumentSchemaUtil { - - private static String dynamicCustomMapping = null; - private static final String DYNAMIC_CUSTOM_TEMPALTE_FILE = - System.getProperty("CONFIG_HOME") + File.separator + "dynamic-custom-template.json"; - - private DocumentSchemaUtil() { // Do not instantiate - } - - public static String generateDocumentMappings(String documentSchema) throws IOException { - // Unmarshal the json content into a document schema object. - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); - return generateDocumentMappings(schema); - } - - public static String generateDocumentMappings(DocumentSchema schema) throws IOException { - // Adding dynamic template to add fielddata=true to dynamic fields of type "string" - // in order to avoid aggregation queries breaking in ESv6.1.2 - if (dynamicCustomMapping == null) { - try { - dynamicCustomMapping = IOUtils.toString(new FileInputStream(DYNAMIC_CUSTOM_TEMPALTE_FILE), "UTF-8") - .replaceAll("\\s+", ""); - } catch (IOException e) { - throw new IOException( - "Dynamic Custom template configuration went wrong! Please check for the correct template file.", - e); - } - } - - // Now, generate the Elastic Search mapping json and return it. - StringBuilder sb = new StringBuilder(); - sb.append("{"); - // Adding custom mapping which adds fielddata=true to dynamic fields of type "string" - sb.append(dynamicCustomMapping != null ? dynamicCustomMapping : ""); - sb.append("\"properties\": {"); - - generateFieldMappings(schema.getFields(), sb); - - sb.append("}"); - sb.append("}"); - - return sb.toString(); - } - - - private static void generateFieldMappings(List fields, StringBuilder sb) { - - AtomicBoolean firstField = new AtomicBoolean(true); - - for (DocumentFieldSchema field : fields) { - - // If this isn't the first field in the list, prepend it with a ',' - if (!firstField.compareAndSet(true, false)) { - sb.append(", "); - } - - // Now, append the translated field contents. - generateFieldMapping(field, sb); - } - } - - private static void generateFieldMapping(DocumentFieldSchema fieldSchema, StringBuilder sb) { - - sb.append("\"").append(fieldSchema.getName()).append("\": {"); - - // The field type is mandatory. - sb.append("\"type\": \"").append(fieldSchema.getDataType()).append("\""); - - // For date type fields we may optionally supply a format specifier. - if (fieldSchema.getDataType().equals("date") && fieldSchema.getFormat() != null) { - sb.append(", \"format\": \"").append(fieldSchema.getFormat()).append("\""); - } - - // If the index field was specified, then append it. - if (fieldSchema.getSearchable() != null) { - sb.append(", \"index\": \"").append(fieldSchema.getSearchable() ? "analyzed" : "not_analyzed").append("\""); - } - - // If a search analyzer was specified, then append it. - if (fieldSchema.getSearchAnalyzer() != null) { - sb.append(", \"search_analyzer\": \"").append(fieldSchema.getSearchAnalyzer()).append("\""); - } - - // If an indexing analyzer was specified, then append it. - if (fieldSchema.getIndexAnalyzer() != null) { - sb.append(", \"analyzer\": \"").append(fieldSchema.getIndexAnalyzer()).append("\""); - } - - - if (fieldSchema.getDataType().equals("nested")) { - - sb.append(", \"properties\": {"); - generateFieldMappings(fieldSchema.getSubFields(), sb); - sb.append("}"); - } - - sb.append("}"); - } - -} - diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java deleted file mode 100644 index d3dd3e1..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslator.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.util; - -import com.jayway.jsonpath.DocumentContext; -import com.jayway.jsonpath.JsonPath; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import org.apache.commons.io.IOUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; - - -/** - * This class as the name suggests is to translate the payload of PUT & POST requests to ElasticSearch (ES) to its - * compatible syntax, specially compatible with ES v6 or above. - * - * For example, data type such as "string" is now replaced by "text" or "keyword". - * - * So this class will make those translations reading off from a json configuration file, therefore the configuration - * can be updated with new translations as and when required without touching the code. - * - * @author EDWINL - * - */ -public class ElasticSearchPayloadTranslator { - - private static Logger logger = - LoggerFactory.getInstance().getLogger(ElasticSearchPayloadTranslator.class.getName()); - private static final String CONFIG_DIRECTORY = System.getProperty("CONFIG_HOME"); - private static final String ES_PAYLOAD_TRANSLATION_FILE = "es-payload-translation.json"; - - private ElasticSearchPayloadTranslator() { // Do not instantiate - } - - /** - * Using JSON Path query to filter objects to translate the payload to ES compatible version The filter queries and - * the replacement attributes are configured in the es-payload-translation.json file. - * - * @param source - * @return translated payload in String - * @throws IOException - */ - public static String translateESPayload(String source) throws IOException { - logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "translateESPayload, method-params[ source=" + source + "]", - "(unknown)"); - String pathToTranslationFile = CONFIG_DIRECTORY + File.separator + ES_PAYLOAD_TRANSLATION_FILE; - - try { - JSONObject translationConfigPayload = - new JSONObject(IOUtils.toString(new FileInputStream(new File(pathToTranslationFile)), "UTF-8")); - JSONArray attrTranslations = translationConfigPayload.getJSONArray("attr-translations"); - DocumentContext payloadToTranslate = JsonPath.parse(source); - - for (Object obj : attrTranslations) { - JSONObject jsonObj = ((JSONObject) obj); - String query = jsonObj.get("query").toString(); - JSONObject attrToUpdate = (JSONObject) jsonObj.get("update"); - List> filteredObjects = payloadToTranslate.read(query); - for (Map objMap : filteredObjects) { - objMap.putAll(attrToUpdate.toMap()); - } - } - - logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, - "Payload after translation: " + payloadToTranslate.jsonString()); - return payloadToTranslate.jsonString(); - } catch (JSONException ex) { - logger.error(SearchDbMsgs.FILTERS_CONFIG_FAILURE, ex, ES_PAYLOAD_TRANSLATION_FILE, ex.getMessage()); - throw new IOException("Payload translation configuration looks corrupted. Please correct!", ex); - } catch (IOException ex) { - logger.error(SearchDbMsgs.FILTERS_CONFIG_FAILURE, ex, ES_PAYLOAD_TRANSLATION_FILE, ex.getMessage()); - throw new IOException("Error in configuring payload translation file. Please check if it exists.", ex); - } - } -} diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java deleted file mode 100644 index fd63741..0000000 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.util; - -public class SearchDbConstants { - - public static final String SDB_FILESEP = - (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); - public static final String SDB_BUNDLECONFIG_NAME = - (System.getProperty("BUNDLECONFIG_DIR") == null) ? "bundleconfig" : System.getProperty("BUNDLECONFIG_DIR"); - - public static final String SDB_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null) - ? SDB_FILESEP + "opt" + SDB_FILESEP + "app" + SDB_FILESEP + "searchdb" + SDB_FILESEP + SDB_BUNDLECONFIG_NAME - : System.getProperty("AJSC_HOME") + SDB_FILESEP + SDB_BUNDLECONFIG_NAME; - - public static final String SDB_HOME_ETC = SDB_HOME_BUNDLECONFIG + SDB_FILESEP + "etc" + SDB_FILESEP; - public static final String SDB_CONFIG_APP_LOCATION = SDB_HOME_ETC + "appprops" + SDB_FILESEP; - - // Elastic Search related - public static final String SDB_SPECIFIC_CONFIG = (System.getProperty("CONFIG_HOME") == null) - ? SDB_CONFIG_APP_LOCATION : System.getProperty("CONFIG_HOME") + SDB_FILESEP; - public static final String ES_CONFIG_FILE = SDB_SPECIFIC_CONFIG + SDB_FILESEP + "elastic-search.properties"; - public static final String SDB_AUTH = SDB_SPECIFIC_CONFIG + "auth" + SDB_FILESEP; - public static final String SDB_AUTH_CONFIG_FILENAME = SDB_AUTH + "search_policy.json"; - public static final String SDB_FILTER_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "filter-config.json"; - public static final String SDB_ANALYSIS_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "analysis-config.json"; - public static final String SDB_SETTINGS_CONFIG_FILE = SDB_SPECIFIC_CONFIG + "settings-config.json"; - - // Logging related - public static final String SDB_SERVICE_NAME = "SearchDataService"; - - private SearchDbConstants() { // Do not instantiate - } - -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 7d169a7..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -server.ssl.key-store=/opt/app/search-data-service/config/auth/tomcat_keystore -server.ssl.enabled=true -server.port=9509 -server.ssl.enabled-protocols=TLSv1.1,TLSv1.2 diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt deleted file mode 100644 index 117d1e4..0000000 --- a/src/main/resources/banner.txt +++ /dev/null @@ -1,5 +0,0 @@ - ____ _ ____ ____ _ _ _ _ _ -/ ___| ___ __ _ _ __ ___| |__ | _ \| __ ) / \ | |__ ___| |_ _ __ __ _ ___| |_(_) ___ _ __ -\___ \ / _ \/ _` | '__/ __| '_ \ _____ | | | | _ \ _____ / _ \ | '_ \/ __| __| '__/ _` |/ __| __| |/ _ \| '_ \ - ___) | __/ (_| | | | (__| | | | |_____| | |_| | |_) | |_____| / ___ \| |_) \__ \ |_| | | (_| | (__| |_| | (_) | | | | -|____/ \___|\__,_|_| \___|_| |_| |____/|____/ /_/ \_\_.__/|___/\__|_| \__,_|\___|\__|_|\___/|_| |_| diff --git a/src/main/resources/json/schema/analyzer.schema.json b/src/main/resources/json/schema/analyzer.schema.json deleted file mode 100644 index 7592ee9..0000000 --- a/src/main/resources/json/schema/analyzer.schema.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Analyzer", - "description": "The analyzer aggregates a tokenizer and multiple filters to describe how an input stream should be indexed.", - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "behaviours": { - "type": "array", - "items": { - "type": "string" - } - }, - "tokenizer": { - "type": "string" - }, - "filters": { - "type": "array", - "items": { - "type": "string" - } - } - } -} \ No newline at end of file diff --git a/src/main/resources/json/schema/document-field.schema.json b/src/main/resources/json/schema/document-field.schema.json deleted file mode 100644 index 78d6cba..0000000 --- a/src/main/resources/json/schema/document-field.schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Document Field Schema", - "description": "Describes the structure of a document field for storage in a document store.", - "type": "object", - "javaType": "org.onap.aai.sa.rest.DocumentFieldSchema", - "properties": { - "name": { - "type": "string" - }, - "data-type": { - "type": "string" - }, - "format": { - "type": "string" - }, - "searchable": { - "type": "boolean" - }, - "search-analyzer": { - "type": "string" - }, - "index-analyzer": { - "type": "string" - }, - "sub-fields": { - "type": "array", - "items": { - "$ref": "document-field.schema.json" - } - } - }, - "required": [ - "name", - "data-type" - ] -} \ No newline at end of file diff --git a/src/main/resources/json/schema/document.schema.json b/src/main/resources/json/schema/document.schema.json deleted file mode 100644 index bbf3e50..0000000 --- a/src/main/resources/json/schema/document.schema.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Document Schema", - "description": "Describes the structure of a document for storage in a document store.", - "type": "object", - "javaType": "org.onap.aai.sa.rest.DocumentSchema", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "document-field.schema.json" - } - } - } -} \ No newline at end of file diff --git a/src/main/resources/json/schema/filter.schema.json b/src/main/resources/json/schema/filter.schema.json deleted file mode 100644 index 6d1a030..0000000 --- a/src/main/resources/json/schema/filter.schema.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Filter", - "description": "Filters accept a stream of tokens from a tokenizer and apply additional rules, possibly producing additional tokens. ", - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "configuration": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/src/main/resources/logging/SearchDbMsgs.properties b/src/main/resources/logging/SearchDbMsgs.properties deleted file mode 100644 index 3e8de80..0000000 --- a/src/main/resources/logging/SearchDbMsgs.properties +++ /dev/null @@ -1,123 +0,0 @@ -#Resource key=Error Code|Message text|Resolution text|Description text -####### -#Newlines can be utilized to add some clarity ensuring continuing line -#has at least one leading space -#ResourceKey=\ -# ERR0000E\ -# Sample error msg txt\ -# Sample resolution msg\ -# Sample description txt -# -###### -#Error code classification category -#000 Info/Debug -#100 Permission errors -#200 Availability errors/Timeouts -#300 Data errors -#400 Schema Interface type/validation errors -#500 Business process errors -#900 Unknown errors -# -######################################################################## -# INFO logs -SERVICE_STARTED=\ - SDB0001I|\ - SearchDB Service started|\ - NA|\ - The SearchDB Service has been started -ELASTIC_SEARCH_CONNECTION_SUCCESS=\ - SDB0002I|\ - Successfully established connection to ElasticSearch {0}|\ - NA|\ - Successfully established connection to ElasticSearch -ELASTIC_SEARCH_CONNECTION_ATTEMPT=\ - SDB0003I|\ - Attempting to connect to ElasticSearch {0}|\ - NA|\ - An attempt is being made to establish connectivity to ElasticSearch -CREATED_INDEX=\ - SDB0019I|\ - Index with name {0} created successfully -DELETED_INDEX=\ - SDB0021I|\ - Deleted index with name {0} -PROCESSED_BULK_OPERATIONS=\ - SDB0022I|\ - Successfully processed a bulk operations request. -PROCESS_EVENT=\ - SDB0041I|\ - Processed event {0}. Result: {1} -PROCESS_INLINE_QUERY=\ - SDB0042I|\ - Processing inline query: {0} -PROCESS_PAYLOAD_QUERY=\ - SDB0043I|\ - Processing query - operation: {0} against URL: {1} -# INFO Level Metrics Logs -CREATE_INDEX_TIME=\ - SDB0020I|\ - Create index request for index {0} document type {1} -DELETE_INDEX_TIME=\ - SDB0022I|\ - Delete index request for index {0} -CREATE_DOCUMENT_TIME=\ - SDB0023|\ - Create document in index {0} -UPDATE_DOCUMENT_TIME=\ - SDB0024|\ - Update document in index {0} with id {1} -DELETE_DOCUMENT_TIME=\ - SDB0025|\ - Delete document in index {0} with id {1} -GET_DOCUMENT_TIME=\ - SDB0026|\ - Get document from index {0} with id {1} -QUERY_DOCUMENT_TIME=\ - SDB0027|\ - Query request for index {0} with query string {1} -BULK_OPERATIONS_TIME=\ - SDB0028|\ - Bulk operations request -CHECK_INDEX_TIME=\ - SDB0029|\ - Check for index {0} -# WARNING logs -INDEX_CREATE_FAILURE=\ - SDB0301W|\ - Failed to create index with index name = {0}. Cause: {1}|\ - Check cause. It is possible the index already exists.|\ - Failed to create the specified index -INDEX_DELETE_FAILURE=\ - SDB0302W|\ - Failed to delete index with index name = {0}. Cause: {1}|\ - Check cause. It is possible the index does not exist.|\ - Failed to delete the specified index -FILTERS_CONFIG_FAILURE=\ - SDB0303W|\ - Failed to read filter configuration from file {0}. Cause: {1} -ANALYSYS_CONFIG_FAILURE=\ - SDB0304W|\ - Failed to read analysis configuration from file {0}. Cause: {1} -GET_ANALYZERS_FAILURE=\ - SDB0305W|\ - Failed to get analyzer definitions. Cause: {0} -BULK_OPERATION_FAILURE=\ - SDB0306W|\ - Failed to execute bulk operations. Cause: {0} -# ERROR logs -ELASTIC_SEARCH_CONNECTION_FAILURE=\ - SDB0501E|\ - Failed to establish connection to ElasticSearch {0}. Cause: {1}|\ - Check connectivity with ElasticSearch. Ensure ElasticSearch is up and reachable.|\ - A connectivity check to ElasticSearch has failed. -EXCEPTION_DURING_METHOD_CALL=\ - SDB0502E|\ - Failed to execute method {0} due to: {1}|\ - Check error cause|\ - Method failed to execute -PROCESS_REST_REQUEST=\ - SDB0503E|\ - Received request {0} {1} from {2}. Sending response: {3} -STARTUP_EXCEPTION=\ - SDB0504E|\ - Exception encountered during startup of search service: {0} diff --git a/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java b/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java deleted file mode 100644 index a4b5395..0000000 --- a/src/test/java/org/onap/aai/sa/auth/SearchDbServiceAuthTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.auth; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; -import org.springframework.http.HttpHeaders; - -// import javax.servlet.http.Cookie; - -public class SearchDbServiceAuthTest { - - @Mock - HttpHeaders headers; - - // @Mock - // Cookie mockedCookie; - - @Before - public void setUp() throws NoSuchFieldException, IllegalAccessException, IOException { - MockitoAnnotations.initMocks(this); - System.setProperty("AJSC_HOME", new File(".").getCanonicalPath().replace('\\', '/')); - setFinalStatic(System.getProperty("AJSC_HOME") + "/src/test/resources/json/search_policy.json"); - } - - @Test - public void testAuthUser() { - SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); - String auth = aaiAuth.authUser(headers, "user-1", "function-1"); - Assert.assertEquals(auth, "AAI_9101"); - } - - // @Test - // public void testAuthCookie_NullCookie(){ - // SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); - // Cookie cookie = null; - // Assert.assertFalse(aaiAuth.authCookie(cookie, "function-1", new StringBuilder("user-1"))); - // } - - // @Test - // public void testAuthCookie_NotNullCookie(){ - // SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); - // Cookie cookie = new Cookie ( "TestCookie", "TestValue"); - // // Cookie cookie = new Cookie ( "TestCookie", "TestValue" ); - // boolean retValue = aaiAuth.authCookie(cookie, "GET:testFunction", new StringBuilder("testuser")); - // Assert.assertTrue(retValue); - // } - - static void setFinalStatic(String fieldValue) - throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - Field configField = SearchDbConstants.class.getDeclaredField("SDB_AUTH_CONFIG_FILENAME"); - configField.setAccessible(true); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(configField, configField.getModifiers() & ~Modifier.FINAL); - - configField.set(null, fieldValue); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java b/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java deleted file mode 100644 index df6ed0e..0000000 --- a/src/test/java/org/onap/aai/sa/rest/ApiUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -import org.junit.Test; - -public class ApiUtilsTest { - - @Test - public void testHTTPStatusConversion() { - assertThat(ApiUtils.getHttpStatusString(201), is(equalTo("Created"))); - assertThat(ApiUtils.getHttpStatusString(207), is(equalTo("Multi-Status"))); - assertThat(ApiUtils.getHttpStatusString(9999), is(equalTo("Unknown"))); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java b/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java deleted file mode 100644 index fcc5b77..0000000 --- a/src/test/java/org/onap/aai/sa/rest/BulkApiTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.io.File; -import java.io.IOException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - - -/** - * This suite of tests validates the behaviour of the bulk operations REST end point. - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = org.onap.aai.sa.Application.class) -@AutoConfigureMockMvc -public class BulkApiTest { - - private final String TOP_URI = "/test/bulk"; - - @Autowired - private MockMvc mockMvc; - - @Test - public void authenticationFailureTest() throws Exception { - - this.mockMvc - .perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON) - .content(SearchServiceApiHarness.FAIL_AUTHENTICATION_TRIGGER)) - .andExpect(status().isForbidden()); - } - - - /** - * This test validates that properly constructed json payloads are correctly validated and that improperly - * contructed payloads will be rejected with the appropriate response code returned to the client. - * - * @throws IOException - */ - @Test - public void payloadValidationTest() throws Exception { - - // Post a request to the bulk operations endpoint with a valid - // operations list payload. - File validBulkOpsFile = new File("src/test/resources/json/bulk-ops-valid.json"); - String validPayloadStr = TestUtils.readFileToString(validBulkOpsFile); - - // Validate that the payload is accepted as expected. - this.mockMvc.perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON).content(validPayloadStr)) - .andExpect(status().isOk()); - - // Post a request to the bulk operations endpoint with an invalid - // operations list payload. - File inValidBulkOpsFile = new File("src/test/resources/json/bulk-ops-invalid.json"); - String inValidPayloadStr = TestUtils.readFileToString(inValidBulkOpsFile); - this.mockMvc.perform(post(TOP_URI).contentType(MediaType.APPLICATION_JSON).content(inValidPayloadStr)) - .andExpect(status().isBadRequest()); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java b/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java deleted file mode 100644 index d5999b8..0000000 --- a/src/test/java/org/onap/aai/sa/rest/BulkRequestTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class BulkRequestTest { - - @Test - public void testBulkRequest_Delete() { - BulkRequest request = new BulkRequest(); - BulkOperation operation = new BulkOperation(); - Document document = new Document(); - BulkMetaData metaData = getMetaData(); - operation.setMetaData(metaData); - operation.setDocument(document); - Assert.assertNotNull(operation.getDocument()); - Assert.assertNotNull(operation.getMetaData()); - Assert.assertNotNull(operation.toString()); - - request.setDelete(operation); - Assert.assertNotNull(request.getDelete()); - Assert.assertEquals(operation, request.getOperation()); - Assert.assertEquals(BulkRequest.OperationType.DELETE, request.getOperationType()); - Assert.assertTrue(request.toString().contains("delete:")); - - - } - - @Test - public void testBulkRequest_Update() { - BulkRequest request = new BulkRequest(); - BulkOperation operation = new BulkOperation(); - Document document = new Document(); - BulkMetaData metaData = getMetaData(); - operation.setMetaData(metaData); - operation.setDocument(document); - Assert.assertNotNull(operation.getDocument()); - Assert.assertNotNull(operation.getMetaData()); - Assert.assertNotNull(operation.toString()); - - request.setUpdate(operation); - Assert.assertNotNull(request.getUpdate()); - Assert.assertEquals(operation, request.getOperation()); - Assert.assertEquals(BulkRequest.OperationType.UPDATE, request.getOperationType()); - Assert.assertTrue(request.toString().contains("update:")); - - } - - @Test - public void testBulkRequest_Create() { - BulkRequest request = new BulkRequest(); - BulkOperation operation = new BulkOperation(); - Document document = new Document(); - BulkMetaData metaData = getMetaData(); - operation.setMetaData(metaData); - operation.setDocument(document); - Assert.assertNotNull(operation.getDocument()); - Assert.assertNotNull(operation.getMetaData()); - Assert.assertNotNull(operation.toString()); - - request.setCreate(operation); - Assert.assertNotNull(request.getCreate()); - Assert.assertEquals(operation, request.getOperation()); - Assert.assertEquals(BulkRequest.OperationType.CREATE, request.getOperationType()); - Assert.assertTrue(request.toString().contains("create:")); - - } - - @Test - public void testBulkRequest_Undefined() { - BulkRequest request = new BulkRequest(); - Assert.assertNull(request.getOperation()); - Assert.assertNull(request.getOperationType()); - Assert.assertEquals("UNDEFINED", request.toString()); - } - - @Test - public void testGetIndex() { - BulkRequest request = new BulkRequest(); - BulkOperation operation = new BulkOperation(); - BulkMetaData metaData = new BulkMetaData(); - metaData.setUrl("/test/indexes/index1"); - operation.setMetaData(metaData); - request.setCreate(operation); - String index = request.getIndex(); - Assert.assertEquals(index, "index1"); - } - - @Test - public void testGetId() { - BulkRequest request = new BulkRequest(); - BulkOperation operation = new BulkOperation(); - BulkMetaData metaData = new BulkMetaData(); - metaData.setUrl("/test/documents/document1"); - operation.setMetaData(metaData); - request.setCreate(operation); - String index = request.getId(); - Assert.assertEquals(index, "document1"); - } - - @Test - public void testApiUtils() { - Assert.assertEquals("services/search-data-service/v1/search/indexes/index1", ApiUtils.buildIndexUri("index1")); - Assert.assertEquals("services/search-data-service/v1/search/indexes/index1/documents/document1", - ApiUtils.buildDocumentUri("index1", "document1")); - Assert.assertTrue(ApiUtils.validateIndexUri("services/search-data-service/v1/search/indexes/index1")); - Assert.assertTrue(ApiUtils.validateDocumentUri( - "services/search-data-service/v1/search/indexes/index1/documents/document1", true)); - Assert.assertTrue(ApiUtils.validateDocumentUri( - "services/search-data-service/v1/search/indexes/index1/documents/document1", false)); - } - - private BulkMetaData getMetaData() { - BulkMetaData metaData = new BulkMetaData(); - metaData.setUrl("http://127.0.0.1"); - metaData.setEtag("etag-1"); - Assert.assertEquals(metaData.getUrl(), "http://127.0.0.1"); - Assert.assertEquals(metaData.getEtag(), "etag-1"); - Assert.assertNotNull(metaData.toString()); - return metaData; - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java b/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java deleted file mode 100644 index 865f981..0000000 --- a/src/test/java/org/onap/aai/sa/rest/DocumentApiTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; - -import java.io.IOException; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class DocumentApiTest { - - private static final String INDEXES_URI = "/test/indexes/"; - private static final String DOCUMENT_URI = "documents/"; - - private static final String SEARCH_URI = "query/"; - private static final String INDEX_NAME = "test-index"; - private static final String DOC_ID = "test-1"; - private static final String SIMPLE_QUERY = - "\"parsed-query\": {\"my-field\": \"something\", \"query-string\": \"string\"}"; - private static final String COMPLEX_QUERY = "{" + "\"filter\": {" + "\"all\": [" - + "{\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}" + "]" + "}," + "\"queries\": [" - + "{\"may\": {\"parsed-query\": {\"field\": \"searchTags\", \"query-string\": \"b\"}}}" + "]" + "}"; - - private static final String CREATE_JSON_CONTENT = "creation content"; - - @Autowired - private MockMvc mockMvc; - - /** - * This test validates the behaviour of the 'Create Document' POST request endpoint. - * - * @throws IOException - * @throws ParseException - */ - @Test - public void createDocumentTest() throws Exception { - - MvcResult result = this.mockMvc.perform(post(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI) - .contentType(MediaType.APPLICATION_JSON).content(CREATE_JSON_CONTENT)).andReturn(); - - // Our stub document store DAO returns the parameters that it was - // passed as the result string, so now we can validate that our - // endpoint invoked it with the correct parameters. - - JSONParser parser = new JSONParser(); - JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); - - assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); - } - - /** - * This test validates the behaviour of the 'Create Document' PUT request endpoint. - * - * @throws IOException - * @throws ParseException - */ - @Test - public void updateDocumentTest() throws Exception { - // WebTarget target = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID); - // Builder request = target.request().header("If-Match", "1"); - // String result = request.put(Entity.json(CREATE_JSON_CONTENT), String.class); - - MvcResult result = this.mockMvc - .perform(put(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) - .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) - .andReturn(); - - // Our stub document store DAO returns the parameters that it was - // passed as the result string, so now we can validate that our - // endpoint invoked it with the correct parameters. - JSONParser parser = new JSONParser(); - JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); - - assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); - } - - /** - * This test validates the behaviour of the 'Get Document' GET request endpoint. - * - * @throws IOException - * @throws ParseException - */ - @Test - public void getDocumentTest() throws Exception { - // String result = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID).request().get(String.class); - - // MvcResult result = this.mockMvc.perform ( get ( INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID ) - // ).andReturn (); - MvcResult result = this.mockMvc - .perform(get(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) - .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) - .andReturn(); - - - // Our stub document store DAO returns the parameters that it was - // passed as the result string, so now we can validate that our - // endpoint invoked it with the correct parameters. - JSONParser parser = new JSONParser(); - JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); - - assertTrue("Unexpected Result ", !json.get("etag").toString().isEmpty()); - - } - - // - // /** - // * This test validates the behaviour of the 'Delete Document' DELETE request - // * endpoint. - // * - // * @throws IOException - // * @throws ParseException - // */ - @Test - public void deleteDocumentTest() throws Exception { - // WebTarget target = target(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID); - // Builder request = target.request().header("If-Match", "1"); - // String result = request.delete(String.class); - MvcResult result = this.mockMvc - .perform(delete(INDEXES_URI + INDEX_NAME + "/" + DOCUMENT_URI + DOC_ID) - .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) - .andReturn(); - - - - // Our stub document store DAO returns the parameters that it was - // passed as the result string, so now we can validate that our - // endpoint invoked it with the correct parameters. - assertTrue("Unexpected Result ", result.getResponse().getContentAsString().isEmpty()); - - } - - - /** - * This test validates the behaviour of the 'Search Documents' GET request endpoint. - * - * @throws Exception - */ - @Ignore - public void searchDocumentTest1() throws Exception { - MvcResult result = this.mockMvc - .perform(get(INDEXES_URI + INDEX_NAME + "/" + SEARCH_URI + SIMPLE_QUERY) - .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content(CREATE_JSON_CONTENT)) - .andReturn(); - - JSONParser parser = new JSONParser(); - JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); - - assertTrue("Unexpected Result ", json.get("totalHits").toString().equals("1")); - } - - /** - * This test validates the behaviour of the 'Search Documents' GET request endpoint. - * - * @throws IOException - * @throws ParseException - */ - @Test - public void searchDocumentTest2() throws Exception { - MvcResult result = this.mockMvc.perform(get(INDEXES_URI + INDEX_NAME + "/" + SEARCH_URI) - .contentType(MediaType.APPLICATION_JSON).content(COMPLEX_QUERY)).andReturn(); - - JSONParser parser = new JSONParser(); - JSONObject json = (JSONObject) parser.parse(result.getResponse().getContentAsString()); - JSONObject resultJson = (JSONObject) json.get("searchResult"); - - assertTrue("Unexpected Result ", resultJson.get("totalHits").toString().equals("1")); - } - -} diff --git a/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java b/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java deleted file mode 100644 index c2d5021..0000000 --- a/src/test/java/org/onap/aai/sa/rest/DocumentSchemaTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import static org.junit.Assert.assertTrue; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.IOException; -import org.junit.Test; - -public class DocumentSchemaTest { - - private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/simpleDocument.json"; - private final String NESTED_DOC_SCHEMA_JSON = "src/test/resources/json/nested-document.json"; - - - /** - * This test validates that we convert document definitions back and forth between json strings and POJOs without - * any loss of data. - * - * @throws com.fasterxml.jackson.core.JsonParseException - * @throws com.fasterxml.jackson.databind.JsonMappingException - * @throws IOException - */ - @Test - public void simpleDocSchemaFromJsonFileTest() throws com.fasterxml.jackson.core.JsonParseException, - com.fasterxml.jackson.databind.JsonMappingException, IOException { - - // Import our json format document schema from a file. - File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); - String fileString = TestUtils.readFileToString(schemaFile); - - // Unmarshall that to a Java POJO - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema docSchema = mapper.readValue(schemaFile, DocumentSchema.class); - - // Now, for the purposes of comparison, produce a JSON string from - // our Java object. - String jsonString = mapper.writeValueAsString(docSchema); - - // Assert that the raw JSON that we read from the file matches the marshalled - // JSON we generated from our Java object (ie: validate that we didn't lose - // anything going in either direction). - assertTrue("Marshalled object does not match the original json source that produced it", - fileString.equals(jsonString)); - } - - // - // /** - // * This test validates that we convert document definitions back and - // * forth between json strings and POJOs without any loss of data in - // * the case of document schemas which contain nested fields. - // * - // * @throws com.fasterxml.jackson.core.JsonParseException - // * @throws com.fasterxml.jackson.databind.JsonMappingException - // * @throws IOException - // */ - - @Test - public void nestedDocSchemaFromJsonFileTest() throws JsonParseException, JsonMappingException, IOException { - - // Import our json format document schema from a file. - File schemaFile = new File(NESTED_DOC_SCHEMA_JSON); - String fileString = TestUtils.readFileToString(schemaFile); - - // Unmarshall that to a Java POJO - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema docSchema = mapper.readValue(schemaFile, DocumentSchema.class); - - String jsonString = mapper.writeValueAsString(docSchema); - - // Assert that the raw JSON that we read from the file matches the marshalled - // JSON we generated from our Java object (ie: validate that we didn't lose - // anything going in either direction). - assertTrue("Marshalled object does not match the original json source that produced it", - fileString.equals(jsonString)); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/DocumentTest.java b/src/test/java/org/onap/aai/sa/rest/DocumentTest.java deleted file mode 100644 index e780e3b..0000000 --- a/src/test/java/org/onap/aai/sa/rest/DocumentTest.java +++ /dev/null @@ -1,727 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import com.fasterxml.jackson.core.JsonProcessingException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -// import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MultivaluedMap; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntity; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.ElasticSearchHttpController; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.ErrorResult; -import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; -import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import java.util.Properties; - - -public class DocumentTest { - - @Mock - SearchServiceApi searchServiceApi; - - @Mock - HttpServletRequest request; - - @Mock - HttpHeaders headers; - - @Mock - HttpServletResponse httpResponse; - - @Mock - DocumentStoreInterface documentStore; - - @Mock - MultivaluedMap multivaluedMap; - - @InjectMocks - IndexApi indexApi; - - DocumentApi documentApi; - - @Mock - ElasticSearchHttpController httpController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - documentApi = new DocumentApi(searchServiceApi); - } - - @Test - public void testDocumentClass_AllMethods() throws JsonProcessingException { - Document doc = new Document(); - doc.setField("name-1", "value-1"); - Assert.assertTrue(doc.getFields().size() == 1); - Assert.assertTrue(doc.toJson().contains("value-1")); - Assert.assertNotNull(doc.toString()); - Assert.assertTrue(doc.toString().contains("name-1")); - } - - @Test - public void testProcessPost_NullContent() { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = null; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - ResponseEntity response = - documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessPost_NotNullContent() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - // - @Test - public void testProcessPost_ValidRequest() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - DocumentOperationResult result = new DocumentOperationResult(); - result.setResultCode(150); - result.setError(new ErrorResult("type-1", "reason-1")); - result.setFailureCause("test-failure"); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), - Mockito.anyBoolean())).thenReturn(result); - Mockito.doNothing().when(httpResponse).setHeader(Mockito.anyString(), Mockito.anyString()); - ResponseEntity response = - documentApi.processPost(content, request, headers, httpResponse, "index", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); - } - - // - @Test - public void testProcessSearchWithGet_Created() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - SearchOperationResult result = new SearchOperationResult(); - result.setResultCode(201); - SearchHits hits = new SearchHits(); - hits.setTotalHits("2"); - result.setSearchResult(hits); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); - ResponseEntity response = - documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.CREATED.value() == response.getStatusCodeValue()); - - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessSearchWithGet_ValidateThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - SearchOperationResult result = new SearchOperationResult(); - result.setResultCode(201); - SearchHits hits = new SearchHits(); - hits.setTotalHits("2"); - result.setSearchResult(hits); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); - ResponseEntity response = - documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - - } - - @Test - public void testProcessSearchWithGet_ValidateIsFalse() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - SearchOperationResult result = new SearchOperationResult(); - result.setResultCode(201); - SearchHits hits = new SearchHits(); - hits.setTotalHits("2"); - result.setSearchResult(hits); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap); - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); - ResponseEntity response = - documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - - } - - @Test - public void testProcessSearchWithGet_InvalidResult() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - SearchOperationResult result = new SearchOperationResult(); - result.setResultCode(302); - SearchHits hits = new SearchHits(); - hits.setTotalHits("2"); - result.setSearchResult(hits); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.search(Mockito.anyString(), Mockito.anyString())).thenReturn(result); - ResponseEntity response = - documentApi.processSearchWithGet(content, request, headers, "index-1", "query-text", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); - - } - - @Test - public void testProcessPut_NullContent() { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = null; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - ResponseEntity response = - documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessPut_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessPut_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = - documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessPut_ResultInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - DocumentOperationResult result = new DocumentOperationResult(); - result.setResultCode(302); - result.setError(new ErrorResult("type-1", "reason-1")); - result.setFailureCause("test-failure"); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), - Mockito.anyBoolean())).thenReturn(result); - ResponseEntity response = - documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessDelete_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessDelete_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = - documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Ignore - @Test - public void testProcessDelete_ResultInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - DocumentOperationResult result = new DocumentOperationResult(); - result.setResultCode(302); - result.setError(new ErrorResult("type-1", "reason-1")); - result.setFailureCause("test-failure"); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.deleteDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class))) - .thenReturn(result); - ResponseEntity response = - documentApi.processDelete(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessGet_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessGet_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = - documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessGet_ResultInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - DocumentOperationResult result = new DocumentOperationResult(); - result.setResultCode(302); - result.setError(new ErrorResult("type-1", "reason-1")); - result.setFailureCause("test-failure"); - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.getDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class))) - .thenReturn(result); - ResponseEntity response = - documentApi.processGet(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); - } - - @Test - public void testQueryWithGetWithPayload_NullContent() { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = null; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - ResponseEntity response = - documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.BAD_REQUEST.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testQueryWithGetWithPayload_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testQueryWithGetWithPayload_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = - documentApi.queryWithGetWithPayload(content, request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testCreateProcessIndex_IndexApi_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = - indexApi.processCreateIndex("document-1", request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testCreateProcessIndex_IndexApi_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = - indexApi.processCreateIndex("document-1", request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @Test - public void testCreateProcessIndex_IndexApi_NullDocument() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String documentSchema = null; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - ResponseEntity response = - indexApi.processCreateIndex(documentSchema, request, headers, "index-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); - } - - @Test - public void testProcessDelete_IndexApi_RequestInvalid() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(false); - ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessDelete_IndexApi_RequestThrowsException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenThrow(IllegalArgumentException.class); - ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcessDelete_IndexApi_DeleteIndexException() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenReturn(true); - Mockito.when(documentStore.deleteIndex(Mockito.anyString())).thenThrow(DocumentStoreOperationException.class); - ResponseEntity response = indexApi.processDelete("document-1", request, headers, documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.INTERNAL_SERVER_ERROR.value() == response.getStatusCodeValue()); - } - - @Test - public void testUserAuthorization() throws Exception { - String transactionId = "transactionId-1"; - String remoteAddr = "http://127.0.0.1"; - String content = "content"; - // Mockito.when(headers.getRequestHeaders()).thenReturn(multivaluedMap);; - Mockito.when(multivaluedMap.getFirst(Mockito.anyString())).thenReturn(transactionId); - Mockito.when(request.getRemoteAddr()).thenReturn(remoteAddr); - Mockito.when(request.getMethod()).thenReturn("testMethod"); - Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://127.0.0.1")); - Mockito.when(request.getRemoteHost()).thenReturn("localhost"); - Mockito.when(searchServiceApi.validateRequest(Mockito.any(HttpHeaders.class), - Mockito.any(HttpServletRequest.class), Mockito.any(ApiUtils.Action.class), Mockito.anyString())) - .thenCallRealMethod(); - - Mockito.doAnswer(new Answer() { - public ElasticSearchConfig answer(InvocationOnMock invocation) { - Properties properties = new Properties(); - return new ElasticSearchConfig(properties); - } - }).when(httpController).getElasticSearchConfig(); - - searchServiceApi.documentStore = httpController; - - ResponseEntity response = - documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - - Mockito.doAnswer(new Answer() { - public ElasticSearchConfig answer(InvocationOnMock invocation) { - Properties properties = new Properties(); - properties.put(ElasticSearchConfig.ES_AUTH_ENABLED, "true"); - return new ElasticSearchConfig(properties); - } - }).when(httpController).getElasticSearchConfig(); - - - response = documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FORBIDDEN.value() == response.getStatusCodeValue()); - - Mockito.doAnswer(new Answer() { - public ElasticSearchConfig answer(InvocationOnMock invocation) { - Properties properties = new Properties(); - properties.put(ElasticSearchConfig.ES_AUTH_ENABLED, "false"); - return new ElasticSearchConfig(properties); - } - }).when(httpController).getElasticSearchConfig(); - - DocumentOperationResult result = new DocumentOperationResult(); - result.setResultCode(302); - result.setError(new ErrorResult("type-1", "reason-1")); - result.setFailureCause("test-failure"); - Mockito.when(documentStore.createDocument(Mockito.anyString(), Mockito.any(DocumentStoreDataEntity.class), - Mockito.anyBoolean())).thenReturn(result); - response = documentApi.processPut(content, request, headers, httpResponse, "index", "id-1", documentStore); - Assert.assertNotNull(response); - Assert.assertTrue(HttpStatus.FOUND.value() == response.getStatusCodeValue()); - - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java b/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java deleted file mode 100644 index ed84a7a..0000000 --- a/src/test/java/org/onap/aai/sa/rest/IndexApiTest.java +++ /dev/null @@ -1,280 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import org.junit.Before; -// import org.glassfish.jersey.server.ResourceConfig; -// import org.glassfish.jersey.test.JerseyTest; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; - -//import javax.ws.rs.core.Application; -//import javax.ws.rs.core.Response; - - -/** - * This suite of tests is intended to exercise the set of REST endpoints associated with manipulating Indexes in the - * document store. - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class IndexApiTest { - - private final String TOP_URI = "/test/indexes/"; - private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/simpleDocument.json"; - private final String DYNAMIC_INDEX_PAYLOAD = "src/test/resources/json/dynamicIndex.json"; - - @Autowired - private MockMvc mockMvc; - - // - // @Override - // protected Application configure() { - // - // // Make sure that our test endpoint is on the resource path - // // for Jersey Test. - // return new ResourceConfig(SearchServiceApiHarness.class); - // } - // - // - - @Before - public void setup() throws Exception { - System.setProperty("CONFIG_HOME", System.getProperty("user.dir") + File.separator + "src/test/resources/json"); - } - - /** - * Tests the dynamic shcema creation flow that send the request JSON to the data store without any JSON validation - * against a schema - * - * @throws IOException - */ - @Test - public void createDynamicIndexTest() throws Exception { - String indexName = "super-ultra-dynamic-mega-index"; - String dynamicUri = TOP_URI + "dynamic/"; - File indexFile = new File(DYNAMIC_INDEX_PAYLOAD); - String indexPayload = TestUtils.readFileToString(indexFile); - - // String result = target(dynamicUri + indexName).request().put(Entity.json(indexPayload), String.class); - MvcResult result = this.mockMvc - .perform(put(dynamicUri + indexName).contentType(MediaType.APPLICATION_JSON).content(indexPayload)) - .andReturn(); - - assertEquals(indexPayload, result.getResponse().getContentAsString()); - } - - - /** - * This test validates that the {@link IndexApi} is able to convert {@link OperationResult} obects to standard REST - * {@link ResponseEntity} objects. - * - * @throws FileNotFoundException - * @throws IOException - * @throws DocumentStoreOperationException - */ - @Test - public void responseFromOperationResultTest() - throws FileNotFoundException, IOException, DocumentStoreOperationException { - - int SUCCESS_RESULT_CODE = 200; - String SUCCESS_RESULT_STRING = "Everything is ay-okay!"; - int FAILURE_RESULT_CODE = 500; - String FAILURE_CAUSE_STRING = "Something went wrong!"; - - - // Create an instance of the index API endpoint that we will test against. - // We will override the init() method because we don't want it to try to - // connect to a real document store. - IndexApi indexApi = new IndexApi(new SearchServiceApiHarness()) { - @Override - public void init() { /* do nothing */ } - }; - // - // Construct an OperationResult instance with a success code and string. - OperationResult successResult = new OperationResult(); - successResult.setResultCode(SUCCESS_RESULT_CODE); - successResult.setResult(SUCCESS_RESULT_STRING); - - // Convert our success OperationResult to a standard REST Response... - ResponseEntity successResponse = indexApi.responseFromOperationResult(successResult); - - // ...and validate that the Response is correctly populated. - assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, successResponse.getStatusCodeValue()); - assertTrue("Incorrect result string", ((String) successResponse.getBody()).equals(SUCCESS_RESULT_STRING)); - - // Construct an OperationResult instance with an error code and failure - // cause. - OperationResult failureResult = new OperationResult(); - failureResult.setResultCode(FAILURE_RESULT_CODE); - failureResult.setFailureCause(FAILURE_CAUSE_STRING); - - // Convert our failure OperationResult to a standard REST Response... - ResponseEntity failureResponse = indexApi.responseFromOperationResult(failureResult); - - // ...and validate that the Response is correctly populated. - assertEquals("Unexpected result code", FAILURE_RESULT_CODE, failureResponse.getStatusCodeValue()); - assertTrue("Incorrect result string", ((String) failureResponse.getBody()).equals(FAILURE_CAUSE_STRING)); - } - - // - // - // /** - // * This test validates the behaviour of the 'Create Index' POST request - // * endpoint. - // * - // * @throws IOException - // */ - @Test - public void createIndexTest() throws Exception { - - String INDEX_NAME = "test-index"; - String EXPECTED_SETTINGS = "{\"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\"]}}}}"; - String EXPECTED_MAPPINGS = - "{\"dynamic_templates\":[{\"strings\":{\"match_mapping_type\":\"string\",\"match\":\"*\",\"mapping\":{\"type\":\"text\",\"fielddata\":true}}}]" - + ",\"properties\": {" + "\"serverName\": {" + "\"type\": \"string\", " - + "\"index\": \"analyzed\", " + "\"search_analyzer\": \"whitespace\"}, " - + "\"serverComplex\": {" + "\"type\": \"string\", " + "\"search_analyzer\": \"whitespace\"}}}"; - - // Read a valid document schema from a json file. - File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); - String documentJson = TestUtils.readFileToString(schemaFile); - - // Send a request to our 'create index' endpoint, using the schema - // which we just read. - // String result = target(TOP_URI + INDEX_NAME).request().put(Entity.json(documentJson), String.class); - MvcResult result = this.mockMvc - .perform(put(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON).content(documentJson)) - .andReturn(); - - - // Our stub document store DAO returns the parameters that it was - // passed as the result string, so now we can validate that our - // endpoint invoked it with the correct parameters. - String[] tokenizedResult = result.getResponse().getContentAsString().split("@"); - assertTrue("Unexpected Index Name '" + tokenizedResult[0] + "' passed to doc store DAO", - tokenizedResult[0].equals(INDEX_NAME)); - assertTrue("Unexpected settings string '" + tokenizedResult[1] + "' passed to doc store DAO", - tokenizedResult[1].equals(EXPECTED_SETTINGS)); - assertTrue("Unexpected mappings string '" + tokenizedResult[2] + "' passed to doc store DAO", - tokenizedResult[2].equals(EXPECTED_MAPPINGS)); - } - - // - // - /** - * This test validates that a 'create index' request with an improperly formatted document schema as the payload - * will result in an appropriate error being returned from the endpoint. - */ - @Test - public void createIndexWithMangledSchemaTest() throws Exception { - - String INDEX_NAME = "test-index"; - int BAD_REQUEST_CODE = 400; - - String invalidSchemaString = "this is definitely not json!"; - - // ResponseEntity result = target(TOP_URI + INDEX_NAME).request().put(Entity.json(invalidSchemaString), - // ResponseEntity.class); - MvcResult result = this.mockMvc - .perform(put(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON).content(invalidSchemaString)) - .andReturn(); - - assertEquals("Invalid document schema should result in a 400 error", BAD_REQUEST_CODE, - result.getResponse().getStatus()); - } - - // - // - /** - * This test validates the behaviour of the 'Delete Index' end point. - */ - @Test - public void deleteIndexTest() throws Exception { - - String INDEX_NAME = "test-index"; - - // Send a request to the 'delete index' endpoint. - // String result = target(TOP_URI + INDEX_NAME).request().delete(String.class); - - MvcResult result = this.mockMvc.perform(delete(TOP_URI + INDEX_NAME).contentType(MediaType.APPLICATION_JSON) - .header("If-Match", "1").content("Some Json")).andReturn(); - - // Validate that the expected parameters were passed to the document - // store DAO. - assertTrue("Unexpected index name '" + result.getResponse().getContentAsString() + "' passed to doc store DAO", - result.getResponse().getContentAsString().equals(INDEX_NAME)); - } - - // - // - // /** - // * This test validates that attempting to delete an index which does not - // * exist results in a 404 error. - // */ - @Test - public void deleteIndexDoesNotExistTest() throws Exception { - - int NOT_FOUND_CODE = 404; - - // Send a request to the 'delete index' endpoint, specifying a - // non-existent index. - // ResponseEntity result = target(TOP_URI + - // StubEsController.DOES_NOT_EXIST_INDEX).request().delete(ResponseEntity.class); - - MvcResult result = - this.mockMvc - .perform(delete(TOP_URI + StubEsController.DOES_NOT_EXIST_INDEX) - .contentType(MediaType.APPLICATION_JSON).header("If-Match", "1").content("Some Json")) - .andReturn(); - - - // Validate that a 404 error code is returned from the end point. - assertEquals("Deleting an index which does not exist should result in a 404 error", NOT_FOUND_CODE, - result.getResponse().getStatus()); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java b/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java deleted file mode 100644 index 93e1d49..0000000 --- a/src/test/java/org/onap/aai/sa/rest/SearchServiceApiHarness.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@Component -@RestController -@RequestMapping("/test") -public class SearchServiceApiHarness extends SearchServiceApi { - - - public static final String FAIL_AUTHENTICATION_TRIGGER = "FAIL AUTHENTICATION"; - - private boolean authenticationShouldSucceed = true; - - - /** - * Performs all one-time initialization required for the end point. - */ - @Override - public void init() { - - // Instantiate our Document Store DAO. - documentStore = new StubEsController(); - } - - @Override - @RequestMapping(value = "/indexes/dynamic/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) - public ResponseEntity processCreateDynamicIndex(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - return super.processCreateDynamicIndex(requestBody, request, headers, index); - } - - - @Override - @RequestMapping(value = "/indexes/{index}", method = RequestMethod.PUT, consumes = {"application/json"}) - public ResponseEntity processCreateIndex(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - return super.processCreateIndex(requestBody, request, headers, index); - } - - @Override - @RequestMapping(value = "/indexes/{index}", method = RequestMethod.DELETE, consumes = {"application/json"}) - public ResponseEntity processDeleteIndex(HttpServletRequest request, @RequestHeader HttpHeaders headers, - @PathVariable("index") String index) { - - return super.processDeleteIndex(request, headers, index); - } - - @Override - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.GET) - public ResponseEntity processGetDocument(HttpServletRequest request, HttpServletResponse httpResponse, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { - - return super.processGetDocument(request, httpResponse, headers, index, id); - } - - @Override - @RequestMapping(value = "/indexes/{index}/documents", method = RequestMethod.POST, - consumes = {"application/json", "application/xml"}) - public ResponseEntity processCreateDocWithoutId(@RequestBody String requestBody, HttpServletRequest request, - HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - return super.processCreateDocWithoutId(requestBody, request, httpResponse, headers, index); - } - - @Override - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.PUT, - consumes = {"application/json", "application/xml"}) - public ResponseEntity processUpsertDoc(@RequestBody String requestBody, HttpServletRequest request, - HttpServletResponse httpResponse, @RequestHeader HttpHeaders headers, @PathVariable("index") String index, - @PathVariable("id") String id) { - - return super.processUpsertDoc(requestBody, request, httpResponse, headers, index, id); - } - - @Override - @RequestMapping(value = "/indexes/{index}/documents/{id}", method = RequestMethod.DELETE, - consumes = {"application/json"}) - public ResponseEntity processDeleteDoc(HttpServletRequest request, HttpServletResponse httpResponse, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index, @PathVariable("id") String id) { - - return super.processDeleteDoc(request, httpResponse, headers, index, id); - } - - @Override - @RequestMapping(value = "/indexes/{index}/query/{queryText}", method = RequestMethod.GET) - public ResponseEntity processInlineQuery(HttpServletRequest request, @RequestHeader HttpHeaders headers, - @PathVariable("index") String index, @PathVariable("queryText") String queryText) { - - return super.processInlineQuery(request, headers, index, queryText); - } - - @Override - @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.GET, consumes = {"application/json"}) - public ResponseEntity processQueryWithGet(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - return super.processQueryWithGet(requestBody, request, headers, index); - } - - @Override - @RequestMapping(value = "/indexes/{index}/query", method = RequestMethod.POST, consumes = {"application/json"}) - public ResponseEntity processQuery(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers, @PathVariable("index") String index) { - - return super.processQuery(requestBody, request, headers, index); - } - - @Override - @RequestMapping(value = "/bulk", method = RequestMethod.POST, consumes = {"application/json"}, - produces = {"application/json"}) - public ResponseEntity processBulkRequest(@RequestBody String requestBody, HttpServletRequest request, - @RequestHeader HttpHeaders headers) { - - // If the operations string contains a special keyword, set the - // harness to fail the authentication validation. - if (requestBody.contains(FAIL_AUTHENTICATION_TRIGGER)) { - authenticationShouldSucceed = false; - } - - // Just pass the request up to the parent, since that is the code - // that we really want to test. - // return super.processPost(operations, request, headers, index); - return super.processBulkRequest(requestBody, request, headers); - } - - @Override - protected boolean validateRequest(HttpHeaders headers, HttpServletRequest req, ApiUtils.Action action, - String authPolicyFunctionName) { - return authenticationShouldSucceed; - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java b/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java deleted file mode 100644 index 9cc4e3b..0000000 --- a/src/test/java/org/onap/aai/sa/rest/SettingConfigurationTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2019 AT&T Intellectual Property. All rights reserved. - * Copyright © 2019 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========================================================= - */ -package org.onap.aai.sa.rest; - -import org.junit.Assert; -import org.junit.Test; - - -public class SettingConfigurationTest { - - @Test - public void settingConfigTest() throws Exception { - SettingConfiguration config = new SettingConfiguration(); - config.init("src/test/resources/json/settings-config.json"); - String settings = config.getSettings(); - System.out.println("SettingsConfig:\n" + settings); - Assert.assertTrue(settings.contains("number_of_shards")); - } - - @Test - public void settingConfigAnalysisTest() throws Exception { - AnalysisConfiguration ac = new AnalysisConfiguration(); - ac.init("src/test/resources/json/filter-config.json", "src/test/resources/json/analysis-config.json"); - System.out.println("AnalysisConfig:\n" + ac.buildEsIndexSettings()); - - SettingConfiguration config = new SettingConfiguration(); - config.init("src/test/resources/json/settings-config.json"); - String settings = config.getSettingsWithAnalysis(ac); - System.out.println("SettingsAnalysisConfig:\n" + settings); - Assert.assertTrue(settings.contains("number_of_shards")); - Assert.assertTrue(settings.contains("nGram_analyzer")); - - config = new SettingConfiguration(); - config.init("src/test/resources/json/missing-file.json"); - settings = config.getSettingsWithAnalysis(ac); - System.out.println("SettingsAnalysisConfigMissing:\n" + settings); - Assert.assertFalse(ac.getEsIndexSettings().isEmpty()); - } -} diff --git a/src/test/java/org/onap/aai/sa/rest/StubEsController.java b/src/test/java/org/onap/aai/sa/rest/StubEsController.java deleted file mode 100644 index cb4edbc..0000000 --- a/src/test/java/org/onap/aai/sa/rest/StubEsController.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.rest; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.json.simple.JSONObject; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreDataEntity; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; -import org.onap.aai.sa.searchdbabstraction.entity.Document; -import org.onap.aai.sa.searchdbabstraction.entity.DocumentOperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import org.onap.aai.sa.searchdbabstraction.entity.SearchHit; -import org.onap.aai.sa.searchdbabstraction.entity.SearchHits; -import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; -import org.onap.aai.sa.searchdbabstraction.util.DocumentSchemaUtil; - -/** - * This class implements a stubbed version of the document store DAO so that we can run unit tests without trying to - * connect to a real document store. - */ -public class StubEsController implements DocumentStoreInterface { - - public static final String DOES_NOT_EXIST_INDEX = "index-does-not-exist"; - - private AnalysisConfiguration analysisConfig = null; - - /** - * - */ - // private IndexAPIHarness indexAPIHarness; - - StubEsController() { - analysisConfig = new AnalysisConfiguration(); - analysisConfig.init("src/test/resources/json/filter-config.json", - "src/test/resources/json/analysis-config.json"); - } - - - @Override - public OperationResult createIndex(String index, DocumentSchema documentSchema) { - - // Just return an OK result, with the parameters that we were passed - // bundled in the response string. This allows unit tests to validate - // that those parameters match what they expected to be passed. - OperationResult opResult = new OperationResult(); - opResult.setResultCode(200); - - try { - opResult.setResult(index + "@" + analysisConfig.getEsIndexSettings() + "@" - + DocumentSchemaUtil.generateDocumentMappings(documentSchema)); - } catch (IOException e) { - e.printStackTrace(); - } - - return opResult; - } - - @Override - public OperationResult createDynamicIndex(String index, String dynamicSchema) { - OperationResult opResult = new OperationResult(); - opResult.setResultCode(200); - // Directly return the json as this flow should not edit the json in any way - opResult.setResult(dynamicSchema); - return opResult; - } - - - @Override - public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { - - OperationResult opResult = new OperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - opResult.setResult(indexName); - } - - return opResult; - } - - @Override - public DocumentOperationResult createDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { - - DocumentOperationResult opResult = buildSampleDocumentOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - opResult.setResultVersion("1"); - } - - return opResult; - } - - @Override - public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, - boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { - - DocumentOperationResult opResult = buildSampleDocumentOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - String version = "1"; - if (document.getVersion() != null) { - version = String.valueOf(Integer.parseInt(document.getVersion()) + 1); - } - opResult.setResultVersion(version); - } - - return opResult; - } - - @Override - public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - DocumentOperationResult opResult = buildSampleDocumentOperationResult(); - - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - if (opResult.getDocument() != null) { - opResult.getDocument().setEtag(null); - opResult.getDocument().setUrl(null); - opResult.setResultVersion("1"); - } - opResult.setResultCode(200); - opResult.setResult(indexName + "@" + document.getId()); - opResult.setResultVersion("1"); - } - - return opResult; - } - - @Override - public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) - throws DocumentStoreOperationException { - DocumentOperationResult opResult = buildSampleDocumentOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - // Adding it to make the tests pass. - opResult.setResultVersion("1"); - } else { - opResult.setResultCode(200); - // Adding it to make the tests pass. - opResult.setResultVersion("1"); - } - - return opResult; - } - - @Override - public SearchOperationResult search(String indexName, String queryText) throws DocumentStoreOperationException { - - SearchOperationResult opResult = buildSampleSearchOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - opResult.setResult(indexName + "@" + queryText); - } - - return opResult; - } - - @Override - public SearchOperationResult searchWithPayload(String indexName, String query) - throws DocumentStoreOperationException { - SearchOperationResult opResult = buildSampleSearchOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - opResult.setResult(indexName + "@" + query); - } - - return opResult; - } - - @Override - public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) - throws DocumentStoreOperationException { - SearchOperationResult opResult = new SearchOperationResult(); - - if (indexName.equals(DOES_NOT_EXIST_INDEX)) { - opResult.setResultCode(404); - } else { - opResult.setResultCode(200); - opResult.setResult(indexName + "@" + query); - } - - return opResult; - } - - @Override - public OperationResult performBulkOperations(BulkRequest[] requests) throws DocumentStoreOperationException { - - OperationResult opResult = new OperationResult(); - opResult.setResultCode(200); - - return opResult; - } - - private DocumentOperationResult buildSampleDocumentOperationResult() { - DocumentOperationResult result = new DocumentOperationResult(); - Document doc = new Document(); - doc.setEtag("etag1"); - - doc.setContent(new JSONObject()); - result.setDocument(doc); - return result; - } - - private SearchOperationResult buildSampleSearchOperationResult() { - SearchOperationResult result = new SearchOperationResult(); - - SearchHits searchHits = new SearchHits(); - SearchHit[] searchHitArray = new SearchHit[1]; - SearchHit searchHit = new SearchHit(); - Document doc = new Document(); - doc.setEtag("etag1"); - Map content = new HashMap<>(); - content.put("key1", "value1"); - doc.setContent(new JSONObject()); - searchHit.setDocument(doc); - searchHitArray[0] = searchHit; - - searchHits.setHits(searchHitArray); - searchHits.setTotalHits("1"); - result.setSearchResult(searchHits); - - return result; - - } - -} diff --git a/src/test/java/org/onap/aai/sa/rest/TestUtils.java b/src/test/java/org/onap/aai/sa/rest/TestUtils.java deleted file mode 100644 index 0d2c615..0000000 --- a/src/test/java/org/onap/aai/sa/rest/TestUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ - -package org.onap.aai.sa.rest; - -import static org.junit.Assert.fail; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -public class TestUtils { - - /** - * This helper method reads the contents of a file into a simple string. - * - * @param aFile - The file to be imported. - * - * @return - The file contents expressed as a simple string. - * - * @throws IOException - */ - public static String readFileToString(File aFile) throws IOException { - - BufferedReader br = new BufferedReader(new FileReader(aFile)); - try { - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - - while (line != null) { - sb.append(line); - line = br.readLine(); - } - - return sb.toString().replaceAll("\\s+", ""); - } finally { - try { - br.close(); - } catch (IOException e) { - fail("Unexpected IOException: " + e.getMessage()); - } - } - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java deleted file mode 100644 index b976f17..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/config/ElasticSearchConfigTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.config; - -import java.util.Properties; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; - -public class ElasticSearchConfigTest { - - @Autowired - ElasticSearchConfig elasticSearchConfig; - - @Before - public void setUp() { - Properties prop = new Properties(); - prop.put("es.cluster-name", "cluster-1"); - prop.put("es.ip-address", "127.0.0.1"); - prop.put("es.http-port", "9001"); - // elasticSearchConfig = new ElasticSearchConfig(prop); - } - - @Ignore - @Test - public void testAllGetMethods() { - Assert.assertEquals(elasticSearchConfig.getClusterName(), "cluster-1"); - Assert.assertEquals(elasticSearchConfig.getIpAddress(), "127.0.0.1"); - Assert.assertEquals(elasticSearchConfig.getHttpPort(), "9001"); - Assert.assertEquals(elasticSearchConfig.getJavaApiPort(), "9300"); - Assert.assertNotNull(elasticSearchConfig.toString()); - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java deleted file mode 100644 index fbc077d..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/AggregationResponseParsingTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.junit.Test; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; -import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; -import org.onap.aai.sa.searchdbabstraction.util.AggregationParsingUtil; - -public class AggregationResponseParsingTest { - - @Test - public void testParseAggregationResponse() { - JSONParser parser = new JSONParser(); - JSONObject root; - - String input = - "{\r\n \"aggregations\": {\r\n \"violations\": {\r\n \"doc_count\": 2,\r\n \"by_Timestamp\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": 7199992,\r\n \"key_as_string\": \"Jan 1 1970 01:59:59\",\r\n \"doc_count\": 2\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n}"; - - try { - root = (JSONObject) parser.parse(input); - JSONObject aggregations = (JSONObject) root.get("aggregations"); - AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); - AggregationResults aggs = new AggregationResults(); - ObjectMapper mapper = new ObjectMapper(); - aggs.setAggregations(results); - System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() - .writeValueAsString(aggs)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void testParseAggregationResponse2() { - JSONParser parser = new JSONParser(); - JSONObject root; - - String input = - "{\r\n \"aggregations\": {\r\n \"entityType\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": \"entity1\",\r\n \"doc_count\": 5,\r\n \"byVersion\": {\r\n \"doc_count_error_upper_bound\": 0,\r\n \"sum_other_doc_count\": 0,\r\n \"buckets\": [\r\n {\r\n \"key\": \"0\",\r\n \"doc_count\": 5\r\n }\r\n ]\r\n }\r\n }\r\n ]\r\n }\r\n }\r\n}"; - - try { - root = (JSONObject) parser.parse(input); - JSONObject aggregations = (JSONObject) root.get("aggregations"); - AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); - AggregationResults aggs = new AggregationResults(); - ObjectMapper mapper = new ObjectMapper(); - aggs.setAggregations(results); - System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() - .writeValueAsString(aggs)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void testParseAggregationResponse3() { - JSONParser parser = new JSONParser(); - JSONObject root; - - String input = - "{\r\n \"aggregations\": {\r\n \"validateTimes\": {\r\n \"buckets\": [\r\n {\r\n \"key\": \"Jan 10 2017 21:6:6-Jan 24 2017 13:43:5\",\r\n \"from\": 1484082366000,\r\n \"from_as_string\": \"Jan 10 2017 21:6:6\",\r\n \"to\": 1485265385000,\r\n \"to_as_string\": \"Jan 24 2017 13:43:5\",\r\n \"doc_count\": 95\r\n },\r\n {\r\n \"key\": \"Feb 3 2017 18:27:39-*\",\r\n \"from\": 1486146459000,\r\n \"from_as_string\": \"Feb 3 2017 18:27:39\",\r\n \"doc_count\": 2\r\n }\r\n ]\r\n }\r\n }\r\n}"; - - try { - root = (JSONObject) parser.parse(input); - JSONObject aggregations = (JSONObject) root.get("aggregations"); - AggregationResult[] results = AggregationParsingUtil.parseAggregationResults(aggregations); - AggregationResults aggs = new AggregationResults(); - ObjectMapper mapper = new ObjectMapper(); - aggs.setAggregations(results); - System.out.println(mapper.setSerializationInclusion(Include.NON_NULL).writerWithDefaultPrettyPrinter() - .writeValueAsString(aggs)); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java deleted file mode 100644 index 007e3fc..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java +++ /dev/null @@ -1,330 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import static org.hamcrest.CoreMatchers.anyOf; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.either; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; - -import java.util.Properties; -import org.eclipse.jetty.util.security.Password; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.onap.aai.sa.rest.AnalysisConfiguration; -import org.onap.aai.sa.rest.DocumentSchema; -import org.onap.aai.sa.rest.SettingConfiguration; -import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; -import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; - -@Ignore("All tests in this classes require an Elasticsearch instance to run locally") -public class ElasticSearchHttpControllerTest { - - static { - // Set the location of the payload translation JSON file. - System.setProperty("CONFIG_HOME", "src/test/resources/json"); - } - - private static ElasticSearchHttpController elasticSearch; - private static AAIEntityTestObject testDocument; - - private static final String TEST_INDEX_NAME = "test"; - - private static final String indexMappings = - "{\r\n \"properties\": {\r\n \"entityType\": {\r\n \"type\": \"text\"\r\n },\r\n" - + " \"edgeTagQueryEntityFieldName\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n" - + " \"edgeTagQueryEntityFieldValue\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n \"searchTagIDs\" : {\r\n \"type\" : \"text\"\r\n },\r\n \"searchTags\": {\r\n \"type\": \"text\",\r\n \"analyzer\": \"nGram_analyzer\",\r\n \"search_analyzer\": \"whitespace_analyzer\"\r\n }\r\n }\r\n}"; - private static final String indexSettings = - "{\r\n \"analysis\": {\r\n \"filter\": {\r\n \"nGram_filter\": {\r\n \"type\": \"nGram\",\r\n \"min_gram\": 1,\r\n \"max_gram\": 50,\r\n \"token_chars\": [\r\n \"letter\",\r\n \"digit\",\r\n \"punctuation\",\r\n \"symbol\"\r\n ]\r\n }\r\n },\r\n \"analyzer\": {\r\n \"nGram_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\",\r\n \"nGram_filter\"\r\n ]\r\n },\r\n \"whitespace_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\"\r\n ]\r\n }\r\n }\r\n }\r\n}"; - - @Before - public void setUp() throws Exception { - Properties properties = new Properties(); - properties.put(ElasticSearchConfig.ES_IP_ADDRESS, "127.0.0.1"); - properties.put(ElasticSearchConfig.ES_HTTP_PORT, "9200"); - properties.put(ElasticSearchConfig.ES_URI_SCHEME, "http"); - properties.put(ElasticSearchConfig.ES_AUTH_USER, "your_user_here"); - properties.put(ElasticSearchConfig.ES_AUTH_ENC, Password.obfuscate("your_password_here")); - elasticSearch = new ElasticSearchHttpController(new ElasticSearchConfig(properties)); - - testDocument = new AAIEntityTestObject(); - testDocument.setId("test123"); - testDocument.setEntityType("service-instance"); - testDocument.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - testDocument.setEdgeTagQueryEntityFieldValue("123456"); - testDocument.setSearchTagIDs("0"); - testDocument.setSearchTags("service-instance-id"); - } - - @Test - public void testGetInstance() throws Exception { - ElasticSearchHttpController.getInstance(); - } - - @Test - public void testCreateIndex() throws Exception { - testDeleteIndex(); - OperationResult result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); - assertThat(result.getResult(), containsString("/search/indexes/test")); - assertThat(result.getResultCode(), is(201)); - - result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); - assertThat(result.getResult(), containsString("already exists")); - assertThat(result.getResultCode(), is(400)); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateDynamicIndexEmptySchema() throws Exception { - elasticSearch.createDynamicIndex(TEST_INDEX_NAME, ""); - } - - @Test - public void testCreateDynamicIndex() throws Exception { - String indexName = "test_dynamic"; - elasticSearch.deleteIndex(indexName); - - OperationResult result = elasticSearch.createDynamicIndex(indexName, - "{\"mappings\":{\"_doc\":{\"dynamic_templates\":[{\"strings_as_text\":{\"match_mapping_type\":\"string\",\"mapping\":{\"type\":\"text\"}}}]}}}"); - assertThat(result.getResult(), containsString("/search/indexes/test")); - assertThat(result.getResultCode(), is(201)); - - elasticSearch.deleteIndex(indexName); - } - - @Test - public void testCreateTable() throws Exception { - AnalysisConfiguration ac = new AnalysisConfiguration(); - ac.init("src/test/resources/json/filter-config.json", "src/test/resources/json/analysis-config.json"); - SettingConfiguration sc = new SettingConfiguration(); - sc.init("src/test/resources/json/settings-config.json"); - - OperationResult result = - elasticSearch.createTable(TEST_INDEX_NAME, "aai-entities", ac, indexMappings, sc); - assertThat(result.getResult(), containsString("\"index\":\"test\"}")); - assertThat(result.getResultCode(), either(is(200)).or(is(400))); - } - - @Test - public void testCreateDocument() throws Exception { - OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, testDocument, false); - assertThat(result.getResult(), not(equalTo(""))); - - DocumentStoreDataEntityImpl ds = new DocumentStoreDataEntityImpl(); - ds.setId(testDocument.getId()); - - result = elasticSearch.getDocument(TEST_INDEX_NAME, ds); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void testCreateDocumentInvalidIndex() throws Exception { - OperationResult result = elasticSearch.createDocument("index_does_not_exist", testDocument, false); - assertThat(result.getResultCode(), is(404)); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void testUpdateDocument() throws Exception { - testDocument.setEdgeTagQueryEntityFieldValue("567890"); - - OperationResult result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); - if (result.getResultCode() == 404) { - testCreateDocument(); - } - // assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); - // assertThat(result.getResult(), containsString("\"found\":true")); - - result = elasticSearch.updateDocument(TEST_INDEX_NAME, testDocument, false); - assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); - - result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); - assertThat(result.getResult(), containsString("test123")); - } - - @Test - public void testDeleteDocument() throws Exception { - OperationResult result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); - if (result.getResultCode() == 404) { - testCreateDocument(); - } - - result = elasticSearch.deleteDocument(TEST_INDEX_NAME, testDocument); - assertThat(result.getResult(), containsString(TEST_INDEX_NAME)); - - result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); - assertThat(result.getResult(), containsString("test123")); - } - - @Test - public void testBulkCreateDocuments() throws Exception { - for (int i = 0; i < 10; i++) { - AAIEntityTestObject doc = new AAIEntityTestObject(); - doc.setId("test-" + i); - doc.setEntityType("service-instance"); - doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - doc.setEdgeTagQueryEntityFieldValue("123456" + i); - doc.setSearchTagIDs("" + i); - doc.setSearchTags("service-instance-id"); - - OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); - assertThat(result.getResultCode(), anyOf(equalTo(201), equalTo(400))); - } - } - - @Test - public void serchByEntityType() throws Exception { - OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=instance"); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void serchByTagIDs() throws Exception { - OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=9"); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void serchByTags() throws Exception { - OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=service"); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void searchWithPayload() throws Exception { - testCreateIndex(); - OperationResult result = - elasticSearch.searchWithPayload(TEST_INDEX_NAME, "{\"query\":{\"term\":{\"user\":\"fred\"}}}"); - assertThat(result.getResult(), containsString("successful")); - assertThat(result.getResultCode(), is(equalTo(200))); - } - - /** - * The _suggest endpoint appears to be deprecated in ES 5.x and above. - */ - @Test - public void suggestionQueryWithPayload() throws Exception { - testCreateIndex(); - OperationResult result = elasticSearch.suggestionQueryWithPayload(TEST_INDEX_NAME, - "{\"my-suggestion\":{\"text\":\"fred\",\"term\":{\"field\":\"body\"}}}"); - assertThat(result.getResult(), containsString("error")); - assertThat(result.getResultCode(), is(equalTo(400))); - } - - @Test - public void testCreateDocumentWithoutId() throws Exception { - AAIEntityTestObject doc = new AAIEntityTestObject(); - doc.setEntityType("service-instance"); - doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - doc.setEdgeTagQueryEntityFieldValue("1111111"); - doc.setSearchTagIDs("321"); - doc.setSearchTags("service-instance-id"); - - OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); - assertThat(result.getResult(), not(equalTo(""))); - } - - @Test - public void testDeleteIndex() throws Exception { - OperationResult result = elasticSearch.deleteIndex(TEST_INDEX_NAME); - assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(404))); - assertThat(result.getResult(), not(equalTo(""))); - } - - class AAIEntityTestObject implements DocumentStoreDataEntity { - private String id; - private String entityType; - private String edgeTagQueryEntityFieldName; - private String edgeTagQueryEntityFieldValue; - private String searchTagIDs; - private String searchTags; - - public void setId(String id) { - this.id = id; - } - - @Override - public String getId() { - return this.id; - } - - public String getEntityType() { - return entityType; - } - - public void setEntityType(String entityType) { - this.entityType = entityType; - } - - public String getEdgeTagQueryEntityFieldName() { - return edgeTagQueryEntityFieldName; - } - - public void setEdgeTagQueryEntityFieldName(String edgeTagQueryEntityFieldName) { - this.edgeTagQueryEntityFieldName = edgeTagQueryEntityFieldName; - } - - public String getEdgeTagQueryEntityFieldValue() { - return edgeTagQueryEntityFieldValue; - } - - public void setEdgeTagQueryEntityFieldValue(String edgeTagQueryEntityFieldValue) { - this.edgeTagQueryEntityFieldValue = edgeTagQueryEntityFieldValue; - } - - public String getSearchTagIDs() { - return searchTagIDs; - } - - public void setSearchTagIDs(String searchTagIDs) { - this.searchTagIDs = searchTagIDs; - } - - public String getSearchTags() { - return searchTags; - } - - public void setSearchTags(String searchTags) { - this.searchTags = searchTags; - } - - @Override - public String getVersion() { - return "1"; - } - - @Override - public String getContentInJson() { - return new JSONObject(). // - put("entityType", entityType) // - .put("edgeTagQueryEntityFieldName", edgeTagQueryEntityFieldName) - .put("edgeTagQueryEntityFieldValue", edgeTagQueryEntityFieldValue) // - .put("searchTagIDs", searchTagIDs) // - .put("searchTags", searchTags) // - .toString(); - } - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java deleted file mode 100644 index 43203c9..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItemTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; - -import org.junit.Assert; -import org.junit.Test; - -public class ElasticSearchResultItemTest { - - @Test - public void testAllMethods() { - ElasticSearchShardStatus shardStatus = new ElasticSearchShardStatus(); - shardStatus.setTotal(10); - shardStatus.setSuccessful(0); - shardStatus.setFailed(1); - Assert.assertEquals(shardStatus.getTotal(), 10); - Assert.assertEquals(shardStatus.getSuccessful(), 0); - Assert.assertEquals(shardStatus.getFailed(), 1); - - ElasticSearchCause cause = new ElasticSearchCause(); - cause.setType("type-1"); - cause.setReason("reason-1"); - Assert.assertEquals(cause.getType(), "type-1"); - Assert.assertEquals(cause.getReason(), "reason-1"); - - ElasticSearchError error = new ElasticSearchError(); - error.setType("type-1"); - error.setReason("reason-1"); - error.setCausedBy(cause); - Assert.assertEquals(error.getType(), "type-1"); - Assert.assertEquals(error.getReason(), "reason-1"); - Assert.assertNotNull(error.getCausedBy()); - error.setAdditionalProperties("name-1", "value-1"); - Assert.assertNotNull(error.getAdditionalProperties()); - - // Create Status - ElasticSearchResultItem resultItem1 = new ElasticSearchResultItem(); - resultItem1.setCreate(getStatus(shardStatus, error)); - Assert.assertNotNull(resultItem1.getCreate()); - Assert.assertEquals(resultItem1.operationType(), "create"); - Assert.assertEquals(resultItem1.operationStatus(), resultItem1.getCreate()); - Assert.assertTrue(resultItem1.toString().contains("create")); - Assert.assertNotNull(resultItem1.toJson()); - - // Index Status - ElasticSearchResultItem resultItem2 = new ElasticSearchResultItem(); - resultItem2.setIndex(getStatus(shardStatus, error)); - Assert.assertNotNull(resultItem2.getIndex()); - Assert.assertEquals(resultItem2.operationType(), "update"); - Assert.assertEquals(resultItem2.operationStatus(), resultItem2.getIndex()); - Assert.assertTrue(resultItem2.toString().contains("index")); - Assert.assertNotNull(resultItem2.toJson()); - - // Delete Status - ElasticSearchResultItem resultItem3 = new ElasticSearchResultItem(); - resultItem3.setDelete(getStatus(shardStatus, error)); - Assert.assertNotNull(resultItem3.getDelete()); - Assert.assertEquals(resultItem3.operationType(), "delete"); - Assert.assertEquals(resultItem3.operationStatus(), resultItem3.getDelete()); - Assert.assertTrue(resultItem3.toString().contains("delete")); - Assert.assertNotNull(resultItem3.toJson()); - - // Unknown Status - ElasticSearchResultItem resultItem4 = new ElasticSearchResultItem(); - Assert.assertEquals(resultItem4.operationType(), "unknown"); - Assert.assertNull(resultItem4.operationStatus()); - - // ElasticSearchBulkOperationResult - ElasticSearchResultItem[] resultItems = {resultItem1, resultItem2, resultItem3}; - ElasticSearchBulkOperationResult result = new ElasticSearchBulkOperationResult(); - result.setErrors(true); - result.setTook(new Integer(10)); - result.setItems(resultItems); - Assert.assertTrue(result.getErrors()); - Assert.assertEquals(result.getTook(), new Integer(10)); - Assert.assertNotNull(result.getItems()); - Assert.assertNotNull(result.toString()); - } - - private ElasticSearchOperationStatus getStatus(ElasticSearchShardStatus shardStatus, ElasticSearchError error) { - ElasticSearchOperationStatus status = new ElasticSearchOperationStatus(); - status.setIndex("index-1"); - status.setType("type-1"); - status.setId("id-1"); - status.setVersion("1.0"); - status.setShards(shardStatus); - status.setStatus(new Integer(1)); - status.setError(error); - status.setAdditionalProperties("REQUEST_URL", "http://127.0.0.1"); - Assert.assertEquals(status.getIndex(), "index-1"); - Assert.assertEquals(status.getType(), "type-1"); - Assert.assertEquals(status.getId(), "id-1"); - Assert.assertEquals(status.getVersion(), "1.0"); - Assert.assertEquals(status.getStatus(), new Integer(1)); - Assert.assertNotNull(status.getShards()); - Assert.assertNotNull(status.getError()); - Assert.assertNotNull(status.getAdditionalProperties()); - return status; - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java deleted file mode 100644 index bff0f4f..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatementTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class AggregationStatementTest { - - private static ObjectMapper mapper = new ObjectMapper(); - - @Test - public void testGroupBy() { - String input = "{\r\n \"group-by\": {\r\n \"field\": \"entityType\"\r\n }\r\n }"; - - String expected = "{\"terms\": {\"field\": \"entityType\"}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - @Test - public void testDateRange() { - String input = - "{\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ],\r\n \"format\": \"MM-yyy\",\r\n \"size\": \"5\"\r\n }\r\n}"; - - String expected = - "{\"date_range\": {\"field\": \"mydate\", \"format\": \"MM-yyy\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}], \"size\": 5}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - @Test - public void testDateHistogram() { - String input = - "{\r\n \"date-histogram\": {\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\"\r\n }\r\n}"; - - String expected = "{\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\"}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - @Test - public void testSubAggregation1() { - String input = - "{\r\n \"group-by\": {\r\n \"field\": \"severity\"\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byType\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"entityType\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; - String expected = - "{\"terms\": {\"field\": \"severity\"}, \"aggs\": {\"byType\": {\"terms\": {\"field\": \"entityType\"}}}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - @Test - public void testSubAggregation2() { - String input = - "{\r\n \"group-by\": {\r\n \"field\": \"severity\"\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byType\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violationType\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"byRule\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"validationRule\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; - String expected = - "{\"terms\": {\"field\": \"severity\"}, \"aggs\": {\"byType\": {\"terms\": {\"field\": \"violationType\"}},\"byRule\": {\"terms\": {\"field\": \"validationRule\"}}}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - - @Test - public void testNestedAggregation1() { - String input = - "{\r\n \"nested\": [{\r\n \"name\": \"by_severity\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.severity\"\r\n }\r\n }\r\n }]\r\n}"; - String expected = - "{\"nested\": {\"path\": \"violations\"}, \"aggs\": {\"by_severity\": {\"terms\": {\"field\": \"violations.severity\"}}}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - @Test - public void testNestedAggregation2() { - String input = - "{\r\n \"nested\": [\r\n {\r\n \"name\": \"by_severity\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.severity\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"by_type\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"violations.violationType\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; - String expected = - "{\"nested\": {\"path\": \"violations\"}, \"aggs\": {\"by_severity\": {\"terms\": {\"field\": \"violations.severity\"}},\"by_type\": {\"terms\": {\"field\": \"violations.violationType\"}}}}"; - - AggregationStatement actual; - try { - actual = mapper.readValue(input, AggregationStatement.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java deleted file mode 100644 index 12b18d1..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class AggregationTest { - private static ObjectMapper mapper = new ObjectMapper(); - - // - @Test - public void test() { - String input = - "{\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ]\r\n },\r\n \"sub-aggregations\": [{\r\n \"name\": \"byTerm\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"myterm\"\r\n }\r\n }\r\n }]\r\n }\r\n}"; - - String expected = - "\"byDate\": {\"date_range\": {\"field\": \"mydate\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}]}, \"aggs\": {\"byTerm\": {\"terms\": {\"field\": \"myterm\"}}}}"; - - Aggregation actual; - try { - actual = mapper.readValue(input, Aggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java deleted file mode 100644 index 005cb76..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateHistogramAggregationTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class DateHistogramAggregationTest { - ObjectMapper mapper = new ObjectMapper(); - - @Test - public void testFullSet() { - String input = "{\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\",\r\n \"time-zone\": \"-01:00\"\r\n}"; - - String expected = - "\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\", \"time_zone\": \"-01:00\"}"; - - DateHistogramAggregation actual; - try { - actual = mapper.readValue(input, DateHistogramAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void test2() { - String input = "{\r\n \"field\": \"mydate\",\r\n \"interval\": \"day\"\r\n}"; - - String expected = "\"date_histogram\": {\"field\": \"mydate\", \"interval\": \"day\"}"; - - DateHistogramAggregation actual; - try { - actual = mapper.readValue(input, DateHistogramAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void test3() { - String input = "{\r\n \"field\": \"mydate\"\r\n}"; - - String expected = "\"date_histogram\": {\"field\": \"mydate\"}"; - - DateHistogramAggregation actual; - try { - actual = mapper.readValue(input, DateHistogramAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java deleted file mode 100644 index 45e7c51..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregationTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class DateRangeAggregationTest { - - private static ObjectMapper mapper = new ObjectMapper(); - - - @Test - public void test() { - - String input = - "{\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\"\r\n }\r\n ],\r\n \"format\": \"MM-yyy\",\r\n \"size\": \"5\"\r\n}"; - String expected = - "\"date_range\": {\"field\": \"mydate\", \"format\": \"MM-yyy\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"from\": \"2016-12-19T00:00:00.738-05:00\"}], \"size\": 5}"; - - DateRangeAggregation actual; - try { - actual = mapper.readValue(input, DateRangeAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void testNoFormatNoSize() { - - String input = - "{\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n },\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\"\r\n }\r\n ]\r\n}"; - String expected = - "\"date_range\": {\"field\": \"mydate\", \"ranges\": [{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"to\": \"2016-12-23T23:59:59.738-05:00\"},{\"from\": \"2016-12-19T00:00:00.738-05:00\"}]}"; - - DateRangeAggregation actual; - try { - actual = mapper.readValue(input, DateRangeAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java deleted file mode 100644 index ef7325e..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class DateRangeTest { - private static ObjectMapper mapper = new ObjectMapper(); - - @Test - public void testBoth() { - String input = - "{\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n}"; - String expected = "{\"from\": \"2016-12-19T00:00:00.738-05:00\", \"to\": \"2016-12-23T23:59:59.738-05:00\"}"; - - DateRange actual; - try { - actual = mapper.readValue(input, DateRange.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void testFrom() { - String input = "{\"from\": \"2016-12-19T00:00:00.738-05:00\"}"; - String expected = "{\"from\": \"2016-12-19T00:00:00.738-05:00\"}"; - - DateRange actual; - try { - actual = mapper.readValue(input, DateRange.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void testTo() { - String input = "{\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n}"; - String expected = "{\"to\": \"2016-12-23T23:59:59.738-05:00\"}"; - - DateRange actual; - try { - actual = mapper.readValue(input, DateRange.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java deleted file mode 100644 index 81fa07f..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/FilterTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import org.junit.Test; - -public class FilterTest { - - @Test - public void test() throws JsonParseException, JsonMappingException, IOException { - - - String json = "{ \"any\": [ " + "{\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}," - + "{\"match\": {\"field\": \"searchTags\", \"value\": \"b\"}}" + "]," + "\"all\": [" - + "{\"parsed-query\": {\"field\": \"fieldname\", \"query-string\": \"string\"}}" + "]" + "}"; - - ObjectMapper mapper = new ObjectMapper(); - Filter filter = mapper.readValue(json, Filter.class); - System.out.println("GDF: filter = " + filter); - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java deleted file mode 100644 index 1ebed91..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/GroupByAggregationTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -public class GroupByAggregationTest { - private static ObjectMapper mapper = new ObjectMapper(); - - @Test - public void test() { - String input = "{\"field\" : \"entityType\", \"size\": 20}\r\n"; - - String expected = "\"terms\": {\"field\": \"entityType\", \"size\": 20}"; - - GroupByAggregation actual; - try { - actual = mapper.readValue(input, GroupByAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - - @Test - public void testNoSize() { - String input = "{\"field\" : \"entityType\"}\r\n"; - - String expected = "\"terms\": {\"field\": \"entityType\"}"; - - GroupByAggregation actual; - try { - actual = mapper.readValue(input, GroupByAggregation.class); - assertEquals(expected, actual.toElasticSearch()); - } catch (Exception e) { - fail("Exception occurred: " + e.getMessage()); - } - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java deleted file mode 100644 index 1f4887f..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/QueryTest.java +++ /dev/null @@ -1,368 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import org.junit.Test; - -public class QueryTest { - - /** - * This test validates that we are able to marshal json structures representing term queries into POJOs and that we - * can then unmarshal those POJOs into ElasticSearch syntax. - * - * @throws JsonParseException - * @throws JsonMappingException - * @throws IOException - */ - @Test - public void termQueryTest() throws JsonParseException, JsonMappingException, IOException { - - Integer intValue = 1; - String field = "searchTags"; - String termQueryWithIntegerValueJson = "{\"field\": \"" + field + "\", \"value\": " + intValue + "}"; - String termQueryWithIntegerValueExpectedES = "{\"term\": {\"" + field + "\" : " + intValue + "}}"; - - Double doubleValue = 5.7; - String termQueryWithDoubleValueJson = "{\"field\": \"" + field + "\", \"value\": " + doubleValue + "}"; - String termQueryWithDoubleValueExpectedES = "{\"term\": {\"" + field + "\" : " + doubleValue + "}}"; - - String stringValue = "theValue"; - String termQueryWithStringValueJson = "{\"field\": \"" + field + "\", \"value\": \"" + stringValue + "\"}"; - String termQueryWithStringValueExpectedES = "{\"term\": {\"" + field + "\" : \"" + stringValue + "\"}}"; - - ObjectMapper mapper = new ObjectMapper(); - - - // Validate that we can marshal a term query where the supplied value - // is an Integer. - TermQuery integerTermQuery = mapper.readValue(termQueryWithIntegerValueJson, TermQuery.class); - assertTrue( - "Expected value to be of type Integer, but was type " - + integerTermQuery.getValue().getClass().getName(), - integerTermQuery.getValue() instanceof Integer); - assertEquals(intValue, integerTermQuery.getValue()); - - assertTrue("ElasticSearch term query translation does not match the expected result", - termQueryWithIntegerValueExpectedES.equals(integerTermQuery.toElasticSearch())); - - // Validate that we can marshal a term query where the supplied value - // is a Double. - TermQuery doubleTermQuery = mapper.readValue(termQueryWithDoubleValueJson, TermQuery.class); - assertTrue( - "Expected value to be of type Double, but was type " + doubleTermQuery.getValue().getClass().getName(), - doubleTermQuery.getValue() instanceof Double); - assertEquals(doubleValue, doubleTermQuery.getValue()); - assertTrue("ElasticSearch term query translation does not match the expected result", - termQueryWithDoubleValueExpectedES.equals(doubleTermQuery.toElasticSearch())); - - // Validate that we can marshal a term query where the supplied value - // is a String literal. - TermQuery stringTermQuery = mapper.readValue(termQueryWithStringValueJson, TermQuery.class); - assertTrue( - "Expected value to be of type String, but was type " + stringTermQuery.getValue().getClass().getName(), - stringTermQuery.getValue() instanceof String); - assertEquals(stringValue, stringTermQuery.getValue()); - assertTrue("ElasticSearch term query translation does not match the expected result", - termQueryWithStringValueExpectedES.equals(stringTermQuery.toElasticSearch())); - - - } - - - /** - * This test validates that we are able to marshal json structures representing parsed queries into POJOs and that - * we can then unmarshal those POJOs into ElasticSearch syntax. - * - * @throws JsonParseException - * @throws JsonMappingException - * @throws IOException - */ - @Test - public void parsedQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "fieldname"; - String queryString = "The query string"; - - String queryJson = "{\"field\": \"" + field + "\", \"query-string\": \"" + queryString + "\"}"; - String queryExpectedES = - "{\"query_string\": {\"default_field\": \"" + field + "\", \"query\": \"" + queryString + "\"}}"; - - ObjectMapper mapper = new ObjectMapper(); - ParsedQuery pq = mapper.readValue(queryJson, ParsedQuery.class); - - assertTrue("Unexpected marshalled value for 'field' - expected: " + field + " actual: " + pq.getField(), - field.equals(pq.getField())); - assertTrue("Unexpected marshalled value for 'query-string' - expected: " + queryString + " actual: " - + pq.getQueryString(), queryString.equals(pq.getQueryString())); - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + queryExpectedES + " Actual: " + pq.toElasticSearch(), - queryExpectedES.equals(pq.toElasticSearch())); - } - - - /** - * This test validates that a ranged query cannot be parsed with values for both the 'gte' and 'gt' fields or the - * 'lte' and 'lt' fields, and that we do not allow mixing of numeric and date types in the same query. - * - * @throws JsonParseException - * @throws IOException - */ - @Test - public void rangeQueryConflictingBoundsTest() throws JsonParseException, IOException { - - String invalidGTAndGTE = - "{ \"field\": \"timestamp\", \"gte\": \"2016-10-06T00:00:00.558+03:00\", \"gt\": \"2016-10-06T23:59:59.558+03:00\"}"; - String invalidLTAndLTE = - "{ \"field\": \"timestamp\", \"lte\": \"2016-10-06T00:00:00.558+03:00\", \"lt\": \"2016-10-06T23:59:59.558+03:00\"}"; - String invalidTypes = "{ \"field\": \"timestamp\", \"lte\": 5, \"gte\": \"2016-10-06T23:59:59.558+03:00\"}"; - - ObjectMapper mapper = new ObjectMapper(); - - // Attempt to parse a query where we are setting values for both the - // 'greater than' and 'greater than and equal to' operators. - boolean gotExpectedException = false; - try { - mapper.readValue(invalidGTAndGTE, RangeQuery.class); - } catch (JsonMappingException e) { - gotExpectedException = true; - } - assertTrue("Attempting to set both a 'gt' and 'gte' value on the same query should not have been allowed", - gotExpectedException); - - // Attempt to parse a query where we are setting values for both the - // 'less than' and 'less than and equal to' operators. - gotExpectedException = false; - try { - mapper.readValue(invalidLTAndLTE, RangeQuery.class); - } catch (JsonMappingException e) { - gotExpectedException = true; - } - assertTrue("Attempting to set both a 'lt' and 'lte' value on the same query should not have been allowed", - gotExpectedException); - - // Attempt to parse a query where we are mixing numeric and date values - // in the same query. - gotExpectedException = false; - try { - mapper.readValue(invalidTypes, RangeQuery.class); - } catch (JsonMappingException e) { - gotExpectedException = true; - } - assertTrue("Attempting to mix numeric and date values in the same query should not have been allowed", - gotExpectedException); - - - } - - - /** - * This test validates that date range queries can be marshalled to a Java POJO and unmarshalled to ElasticSearch - * syntax. - * - * @throws JsonParseException - * @throws JsonMappingException - * @throws IOException - */ - @Test - public void dateRangeQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "timestamp"; - String greaterThanDate = "2016-10-06T00:00:00.558+03:00"; - String lessThanDate = "2016-10-06T23:59:59.558+03:00"; - - ObjectMapper mapper = new ObjectMapper(); - - // Generate a date range query using 'greater than or equal' and 'less - // than or equal' operations. - String dateRangeJson = "{ \"field\": \"" + field + "\", \"gte\": \"" + greaterThanDate + "\", \"lte\": \"" - + lessThanDate + "\"}"; - String dateRangeExpectedES = - "{\"range\": {\"timestamp\": {\"gte\": \"2016-10-06T00:00:00.558+03:00\", \"lte\": \"2016-10-06T23:59:59.558+03:00\"}}}"; - - // Validate that the query is marshalled correctly to the POJO and that - // the generated ElasticSearch syntax looks as expected. - RangeQuery dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); - - assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " - + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); - assertTrue("Unexpected type for 'gte' value. Expected: String Actual: " - + dateRangeQuery.getGte().getClass().getName(), dateRangeQuery.getGte() instanceof String); - assertTrue("Unexpected type for 'lte' value. Expected: String Actual: " - + dateRangeQuery.getLte().getClass().getName(), dateRangeQuery.getLte() instanceof String); - assertTrue("Unexpected marshalled value for 'gte'. Expected: " + greaterThanDate + " Actual: " - + dateRangeQuery.getGte(), greaterThanDate.equals(dateRangeQuery.getGte())); - assertTrue("Unexpected marshalled value for 'lte'. Expected: " + lessThanDate + " Actual: " - + dateRangeQuery.getLte(), lessThanDate.equals(dateRangeQuery.getLte())); - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " - + dateRangeQuery.toElasticSearch(), - dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); - - - // Generate a date range query using 'greater than' and 'less than or - // equal' operations. - dateRangeJson = "{ \"field\": \"" + field + "\", \"gt\": \"" + greaterThanDate + "\", \"lte\": \"" - + lessThanDate + "\"}"; - dateRangeExpectedES = - "{\"range\": {\"timestamp\": {\"gt\": \"2016-10-06T00:00:00.558+03:00\", \"lte\": \"2016-10-06T23:59:59.558+03:00\"}}}"; - - // Validate that the query is marshalled correctly to the POJO and that - // the generated ElasticSearch syntax looks as expected. - dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); - - assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " - + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); - - assertTrue("Unexpected type for 'gt' value. Expected: String Actual: " - + dateRangeQuery.getGt().getClass().getName(), dateRangeQuery.getGt() instanceof String); - - assertTrue("Unexpected type for 'lte' value. Expected: String Actual: " - + dateRangeQuery.getLte().getClass().getName(), dateRangeQuery.getLte() instanceof String); - - assertTrue("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDate + " Actual: " - + dateRangeQuery.getGt(), greaterThanDate.equals(dateRangeQuery.getGt())); - - assertTrue("Unexpected marshalled value for 'lte'. Expected: " + lessThanDate + " Actual: " - + dateRangeQuery.getLte(), lessThanDate.equals(dateRangeQuery.getLte())); - - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " - + dateRangeQuery.toElasticSearch(), - dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); - - - // Generate a date range query using only a 'greater than' operation. - dateRangeJson = "{ \"field\": \"" + field + "\", \"gt\": \"" + greaterThanDate + "\"}"; - dateRangeExpectedES = "{\"range\": {\"timestamp\": {\"gt\": \"2016-10-06T00:00:00.558+03:00\"}}}"; - - // Validate that the query is marshalled correctly to the POJO and that - // the generated ElasticSearch syntax looks as expected. - dateRangeQuery = mapper.readValue(dateRangeJson, RangeQuery.class); - - assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " - + dateRangeQuery.getField(), field.equals(dateRangeQuery.getField())); - - assertTrue("Unexpected type for 'gt' value. Expected: String Actual: " - + dateRangeQuery.getGt().getClass().getName(), dateRangeQuery.getGt() instanceof String); - - assertTrue("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDate + " Actual: " - + dateRangeQuery.getGt(), greaterThanDate.equals(dateRangeQuery.getGt())); - - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + dateRangeExpectedES + " Actual: " - + dateRangeQuery.toElasticSearch(), - dateRangeExpectedES.equals(dateRangeQuery.toElasticSearch())); - - } - - /** - * This test validates that numeric range queries can be marshalled to a Java POJO and unmarshalled to ElasticSearch - * syntax. - * - * @throws JsonParseException - * @throws JsonMappingException - * @throws IOException - */ - @Test - public void numericRangeQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "version"; - Integer greaterThanInt = 5; - Integer lessThanInt = 100; - - ObjectMapper mapper = new ObjectMapper(); - - // Generate a numeric range query using 'greater than or equal' and 'less - // than or equal' operations. - String numericRangeJson = - "{ \"field\": \"" + field + "\", \"gte\": " + greaterThanInt + ", \"lte\": " + lessThanInt + "}"; - String numericRangeExpectedES = - "{\"range\": {\"" + field + "\": {\"gte\": " + greaterThanInt + ", \"lte\": " + lessThanInt + "}}}"; - - // Validate that the query is marshalled correctly to the POJO and that - // the generated ElasticSearch syntax looks as expected. - RangeQuery numericRangeQuery = mapper.readValue(numericRangeJson, RangeQuery.class); - - assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " - + numericRangeQuery.getField(), field.equals(numericRangeQuery.getField())); - assertTrue( - "Unexpected type for 'gte' value. Expected: Integer Actual: " - + numericRangeQuery.getGte().getClass().getName(), - numericRangeQuery.getGte() instanceof Integer); - assertTrue( - "Unexpected type for 'lte' value. Expected: Integer Actual: " - + numericRangeQuery.getLte().getClass().getName(), - numericRangeQuery.getLte() instanceof Integer); - assertEquals("Unexpected marshalled value for 'gte'. Expected: " + greaterThanInt + " Actual: " - + numericRangeQuery.getGte(), greaterThanInt, numericRangeQuery.getGte()); - assertEquals("Unexpected marshalled value for 'lte'. Expected: " + lessThanInt + " Actual: " - + numericRangeQuery.getLte(), lessThanInt, numericRangeQuery.getLte()); - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + numericRangeExpectedES + " Actual: " - + numericRangeQuery.toElasticSearch(), - numericRangeExpectedES.equals(numericRangeQuery.toElasticSearch())); - - - Double greaterThanDouble = 5.0; - Double lessThanDouble = 100.0; - - // Generate a date range query using 'greater than' and 'less than or - // equal' operations. - numericRangeJson = - "{ \"field\": \"" + field + "\", \"gt\": " + greaterThanDouble + ", \"lte\": " + lessThanDouble + "}"; - numericRangeExpectedES = "{\"range\": {\"" + field + "\": {\"gt\": " + greaterThanDouble + ", \"lte\": " - + lessThanDouble + "}}}"; - - // Validate that the query is marshalled correctly to the POJO and that - // the generated ElasticSearch syntax looks as expected. - numericRangeQuery = mapper.readValue(numericRangeJson, RangeQuery.class); - - assertTrue("Unexpected marshalled value for 'field'. Expected: " + field + " Actual: " - + numericRangeQuery.getField(), field.equals(numericRangeQuery.getField())); - - assertTrue("Unexpected type for 'gt' value. Expected: Double Actual: " - + numericRangeQuery.getGt().getClass().getName(), numericRangeQuery.getGt() instanceof Double); - - assertTrue( - "Unexpected type for 'lte' value. Expected: Double Actual: " - + numericRangeQuery.getLte().getClass().getName(), - numericRangeQuery.getLte() instanceof Double); - - assertEquals("Unexpected marshalled value for 'gt'. Expected: " + greaterThanDouble + " Actual: " - + numericRangeQuery.getGt(), greaterThanDouble, numericRangeQuery.getGt()); - - assertEquals("Unexpected marshalled value for 'lte'. Expected: " + lessThanDouble + " Actual: " - + numericRangeQuery.getLte(), lessThanDouble, numericRangeQuery.getLte()); - - assertTrue( - "Unexpected ElasticSearch syntax. Expected: " + numericRangeExpectedES + " Actual: " - + numericRangeQuery.toElasticSearch(), - numericRangeExpectedES.equals(numericRangeQuery.toElasticSearch())); - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java deleted file mode 100644 index e58e545..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/RangeQueryTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.IOException; -import org.junit.Assert; -import org.junit.Test; -import org.onap.aai.sa.rest.TestUtils; - -public class RangeQueryTest { - - static { - // Set the location of the payload translation JSON file. - System.setProperty("CONFIG_HOME", "src/test/resources/json"); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetGt() { - RangeQuery rq = new RangeQuery(); - rq.setLt(new String("2x")); - Assert.assertEquals("2x", rq.getLt()); - Assert.assertNotNull(rq.toElasticSearch()); - Assert.assertNotNull(rq.toString()); - rq.setGt(new Integer(1)); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetGte() { - RangeQuery rq = new RangeQuery(); - rq.setGt(new Integer(1)); - Assert.assertNotNull(rq.toElasticSearch()); - Assert.assertNotNull(rq.toString()); - rq.setGte(new Integer(1)); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetLt() { - RangeQuery rq = new RangeQuery(); - rq.setLt(new Integer(1)); - rq.setFormat("format-1"); - assertThat(rq.getFormat(), is(equalTo("format-1"))); - Assert.assertNotNull(rq.toElasticSearch()); - Assert.assertNotNull(rq.toString()); - - rq.setGt(new Integer(1)); - Assert.assertNotNull(rq.toElasticSearch()); - Assert.assertNotNull(rq.toString()); - rq.setLt(new String("10")); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetLte() { - RangeQuery rq = new RangeQuery(); - rq.setGt(new Integer(1)); - rq.setTimeZone("CT"); - assertThat(rq.getTimeZone(), is(equalTo("CT"))); - Assert.assertNotNull(rq.toElasticSearch()); - Assert.assertNotNull(rq.toString()); - - rq.setLte(new String("10")); - } - - @Test - public void testSearchStatementAggregations() throws IOException { - File queryWithSubrangeFile = new File("src/test/resources/json/queries/query-with-subrange.json"); - String queryWithSubrangeStr = TestUtils.readFileToString(queryWithSubrangeFile); - - ObjectMapper mapper = new ObjectMapper(); - SearchStatement ss = mapper.readValue(queryWithSubrangeStr, SearchStatement.class); - - Aggregation a1 = getAggregationObject(); - Aggregation a2 = getAggregationObject(); - Aggregation[] aggs = new Aggregation[] {a1, a2}; - ss.setAggregations(aggs); - Assert.assertNotNull(ss.toString()); - } - - private Aggregation getAggregationObject() { - Aggregation a = new Aggregation(); - - AggregationStatement as = new AggregationStatement(); - DateHistogramAggregation dha = new DateHistogramAggregation(); - dha.setField("field-1"); - dha.setInterval("interval-1"); - assertThat(dha.getInterval(), is(equalTo("interval-1"))); - dha.setTimeZone("CT"); - assertThat(dha.getTimeZone(), is(equalTo("CT"))); - dha.setFormat("format-1"); - assertThat(dha.getFormat(), is(equalTo("format-1"))); - dha.setSize(10); - dha.setMinThreshold(1); - Assert.assertNotNull(dha.toElasticSearch()); - Assert.assertNotNull(dha.toString()); - as.setDateHist(dha); - as.toString(); - - as.getNestedPath(); - - DateRangeAggregation dra = new DateRangeAggregation(); - dra.setField("field-1"); - dra.setMinThreshold(1); - dra.setFormat("format-1"); - assertThat(dra.getFormat(), is(equalTo("format-1"))); - DateRange dr = new DateRange(); - dr.setFromDate("01-12-2017"); - assertThat(dr.getFromDate(), is(equalTo("01-12-2017"))); - dr.setToDate("21-12-2017"); - assertThat(dr.getToDate(), is(equalTo("21-12-2017"))); - DateRange[] drs = {dr}; - dra.setDateRanges(drs); - Assert.assertTrue(dra.getDateRanges().length == 1); - Assert.assertNotNull(dra.toElasticSearch()); - Assert.assertNotNull(dra.toString()); - as.setDateRange(dra); - as.toString(); - - as.getNestedPath(); - - GroupByAggregation gba = new GroupByAggregation(); - gba.setField("field-1"); - gba.setMinThreshold(1); - Assert.assertNotNull(gba.toElasticSearch()); - Assert.assertNotNull(gba.toString()); - as.setGroupBy(gba); - Assert.assertNotNull(as.toString()); - - a.setStatement(as); - Assert.assertNotNull(a.toString()); - return a; - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java deleted file mode 100644 index 45ad666..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatementTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.File; -import java.io.IOException; -import org.junit.Test; -import org.onap.aai.sa.rest.TestUtils; - -public class SearchStatementTest { - - @Test - public void simpleQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "searchTags"; - String queryString = "aai3255"; - String queryJson = "{" + "\"queries\": [" + "{\"may\": {\"parsed-query\": {" + "\"field\": \"" + field + "\"," - + "\"query-string\": \"" + queryString + "\"}}}" + "]" + "}" + "}"; - - String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " - + "\"should\": [" + "{\"query_string\": {\"default_field\": \"searchTags\", \"query\": \"aai3255\"}}" - + "]," + "\"must_not\": []}" + "}" + "}"; - - // Marshal our simple query JSON to a SearchStatement object. - ObjectMapper mapper = new ObjectMapper(); - SearchStatement ss = mapper.readValue(queryJson, SearchStatement.class); - - // We expect to have a search statement with one query. - assertEquals("Unexpected number of queries in marshalled result", 1, ss.getQueries().length); - - // Validate that the query is of the expected type and contains the - // expected values. - QueryStatement query = ss.getQueries()[0].getQueryStatement(); - assertNotNull("Expected marshalled statement to contain a 'parsed query'", query.getParsedQuery()); - assertTrue("Unexpected field name in marshalled query. Expected: " + field + " Actual: " - + query.getParsedQuery().getField(), field.equals(query.getParsedQuery().getField())); - assertTrue( - "Unexpected query string in marshalled query. Expected: " + queryString + " Actual: " - + query.getParsedQuery().getQueryString(), - queryString.equals(query.getParsedQuery().getQueryString())); - - // Validate that we are able to produce the expected ElasticSearch - // query syntax from the search statement. - assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), - queryES.equals(ss.toElasticSearch())); - } - - - @Test - public void simpleSortedQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "searchTags"; - String queryString = "aai3255"; - String queryJson = "{" + "\"queries\": [" + "{\"may\": {\"parsed-query\": {" + "\"field\": \"" + field + "\"," - + "\"query-string\": \"" + queryString + "\"}}}" + "]," - + "\"sort\": { \"field\": \"date\", \"order\": \"ascending\" }" + "}"; - - - String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " - + "\"should\": [" + "{\"query_string\": {\"default_field\": \"searchTags\", \"query\": \"aai3255\"}}" - + "]," + "\"must_not\": []" + "}" + "}, " + "\"sort\": { \"date\": { \"order\": \"asc\"}}" + "}"; - - // Marshal our simple query JSON to a SearchStatement object. - ObjectMapper mapper = new ObjectMapper(); - SearchStatement ss = mapper.readValue(queryJson, SearchStatement.class); - - // We expect to have a search statement with one query. - assertEquals("Unexpected number of queries in marshalled result", 1, ss.getQueries().length); - - // Validate that the query is of the expected type and contains the - // expected values. - QueryStatement query = ss.getQueries()[0].getQueryStatement(); - assertNotNull("Expected marshalled statement to contain a 'parsed query'", query.getParsedQuery()); - assertTrue("Unexpected field name in marshalled query. Expected: " + field + " Actual: " - + query.getParsedQuery().getField(), field.equals(query.getParsedQuery().getField())); - assertTrue( - "Unexpected query string in marshalled query. Expected: " + queryString + " Actual: " - + query.getParsedQuery().getQueryString(), - queryString.equals(query.getParsedQuery().getQueryString())); - System.out.println("GDF: ES = " + ss.toElasticSearch()); - // Validate that we are able to produce the expected ElasticSearch - // query syntax from the search statement. - assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), - queryES.equals(ss.toElasticSearch())); - assertNull(ss.getAggregations()); - } - - @Test - public void filteredQueryTest() throws JsonParseException, JsonMappingException, IOException { - - String filterField1 = "field1"; - String filterField2 = "field2"; - String filterField3 = "field3"; - String filterValue1 = "a"; - String filterValue2 = "b"; - String filterValue3 = "string"; - String filterJson = "{ \"any\": [ " + "{\"match\": {\"field\": \"" + filterField1 + "\", \"value\": \"" - + filterValue1 + "\"}}," + "{\"match\": {\"field\": \"" + filterField2 + "\", \"value\": \"" - + filterValue2 + "\"}}" + "]," + "\"all\": [" + "{\"parsed-query\": {\"field\": \"" + filterField3 - + "\", \"query-string\": \"" + filterValue3 + "\"}}" + "]" + "}"; - - String filterStanzaJson = "\"filter\": " + filterJson; - - String queryStanzaJson = "\"queries\": [ " - + "{\"may\": {\"match\": {\"field\": \"searchTags\", \"value\": \"a\"}}}," - + "{\"may\": {\"match\": {\"field\": \"searchTags\", \"value\": \"b\"}}}," - + "{\"may\": {\"parsed-query\": {\"field\": \"fieldname\", \"query-string\": \"string\"}}}" + "]"; - - String queryES = "{" + "\"version\": true," + "\"query\": {" + "\"bool\": {" + "\"must\": [], " - + "\"should\": [" + "{\"term\": {\"searchTags\" : \"a\"}}, " + "{\"term\": {\"searchTags\" : \"b\"}}, " - + "{\"query_string\": {\"default_field\": \"fieldname\", \"query\": \"string\"}}" + "]," - + "\"must_not\": [], " + "\"filter\": {" + "\"bool\": {" + "\"must\": [" - + "{\"query_string\": {\"default_field\": \"field3\", \"query\": \"string\"}}" + "]," - + "\"must_not\": []," + "\"should\": [" + "{\"term\": {\"field1\" : \"a\"}}, " - + "{\"term\": {\"field2\" : \"b\"}}" + "]," + "\"must_not\": []" + "}" + "}" + "}" + "}" + "}"; - - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append(filterStanzaJson).append(", "); - sb.append(queryStanzaJson); - sb.append("}"); - - ObjectMapper mapper = new ObjectMapper(); - SearchStatement ss = mapper.readValue(sb.toString(), SearchStatement.class); - - assertEquals("Unexpected number of queries in the 'any' list for this statement's filter", 2, - ss.getFilter().getAny().length); - assertEquals("Unexpected number of queries in the 'all' list for this statement's filter", 1, - ss.getFilter().getAll().length); - - assertTrue("Unexpected ElasticSearch syntax. Expected: " + queryES + " Actual: " + ss.toElasticSearch(), - queryES.equals(ss.toElasticSearch())); - - assertNull(ss.getAggregations()); - } - - @Test - public void aggregationTest() { - String input = - "{\r\n \"queries\": [\r\n {\r\n \"must\": {\r\n \"match\": {\r\n \"field\": \"searchTags\",\r\n \"value\": \"a\"\r\n }\r\n }\r\n }\r\n ],\r\n \"aggregations\": [\r\n {\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-range\": {\r\n \"field\": \"mydate\",\r\n \"ranges\": [\r\n {\r\n \"from\": \"2016-12-19T00:00:00.738-05:00\",\r\n \"to\": \"2016-12-23T23:59:59.738-05:00\"\r\n }\r\n ]\r\n },\r\n \"sub-aggregations\": [\r\n {\r\n \"name\": \"byTerm\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"myterm\"\r\n }\r\n }\r\n },\r\n {\r\n \"name\": \"byDate\",\r\n \"aggregation\": {\r\n \"date-histogram\": {\r\n \"field\": \"myDate\",\r\n \"interval\": \"myInterval\"\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n },\r\n {\r\n \"name\": \"2nd\",\r\n \"aggregation\": {\r\n \"group-by\": {\r\n \"field\": \"anotherTerm\"\r\n }\r\n }\r\n }\r\n ]\r\n}"; - - ObjectMapper mapper = new ObjectMapper(); - try { - SearchStatement ss = mapper.readValue(input, SearchStatement.class); - Aggregation[] aggs = ss.getAggregations(); - assertNotNull(aggs); - assertEquals("Unexpected number aggregations", 2, aggs.length); - assertEquals("byDate", aggs[0].getName()); - assertNotNull(aggs[0].getStatement().getDateRange()); - assertEquals("mydate", aggs[0].getStatement().getDateRange().getField()); - assertNotNull(aggs[0].getStatement().getSubAggregations()); - assertEquals(2, aggs[0].getStatement().getSubAggregations().length); - assertEquals("byTerm", aggs[0].getStatement().getSubAggregations()[0].getName()); - assertEquals("byDate", aggs[0].getStatement().getSubAggregations()[1].getName()); - assertNull(aggs[0].getStatement().getGroupBy()); - assertEquals("2nd", aggs[1].getName()); - assertNotNull(aggs[1].getStatement().getGroupBy()); - assertEquals("anotherTerm", aggs[1].getStatement().getGroupBy().getField()); - assertNull(aggs[1].getStatement().getDateRange()); - assertNull(aggs[1].getStatement().getSubAggregations()); - - } catch (Exception e) { - fail("Encountered exception: " + e.getMessage()); - } - } - - @Test - public void resultSetRangeTest() throws IOException { - - // Simple query with a result set subrange specified. - File queryWithSubrangeFile = new File("src/test/resources/json/queries/query-with-subrange.json"); - String queryWithSubrangeStr = TestUtils.readFileToString(queryWithSubrangeFile); - String queryWithSubrangeExpectedESString = - "{\"version\": true,\"from\": 0, \"size\": 10, \"query\": {\"bool\": {\"must\": [{\"term\": {\"field1\" : \"Bob\"}}], \"should\": [],\"must_not\": []}}}"; - - ObjectMapper mapper = new ObjectMapper(); - SearchStatement ss = mapper.readValue(queryWithSubrangeStr, SearchStatement.class); - - assertEquals("Unexpected index for result set start", ss.getFrom(), (Integer) 0); - assertEquals("Unexpected value for result set size", ss.getSize(), (Integer) 10); - assertTrue("Unexpected elastic search query generated from search statement", - ss.toElasticSearch().equals(queryWithSubrangeExpectedESString)); - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java deleted file mode 100644 index 832fa98..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/SortTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import static org.junit.Assert.assertTrue; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import org.junit.Test; - -public class SortTest { - - @Test - public void sortFieldTest() throws JsonParseException, JsonMappingException, IOException { - - String field = "fieldname"; - String order = "ascending"; - String json = "{\"field\": \"" + field + "\", \"order\": \"" + order + "\"}"; - - ObjectMapper mapper = new ObjectMapper(); - Sort sort = mapper.readValue(json, Sort.class); - - assertTrue("Unexpected field name in marshalled object. Expected: " + field + " Actual: " + sort.getField(), - field.equals(sort.getField())); - assertTrue("Unexpected order field in marshalled object. Expected: " + order + " Actual: " + sort.getOrder(), - order.equals(sort.getOrder().toString())); - - } -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java deleted file mode 100644 index 5a15913..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/searchapi/TermQueryTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.searchapi; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import org.junit.Assert; -import org.junit.Test; - -public class TermQueryTest { - - @Test - public void testAllMethods() throws IOException { - String field = "searchTags.nested"; - String stringValue = "theValue.nested"; - String termQueryWithStringValueJson = "{\"field\": \"" + field + "\", \"value\": \"" + stringValue + "\"}"; - - ObjectMapper mapper = new ObjectMapper(); - TermQuery stringTermQuery = mapper.readValue(termQueryWithStringValueJson, TermQuery.class); - Assert.assertEquals(stringValue, stringTermQuery.getValue()); - Assert.assertEquals("searchTags.nested", stringTermQuery.getField()); - stringTermQuery.setOperator("operator-1"); - Assert.assertEquals("operator-1", stringTermQuery.getOperator()); - stringTermQuery.setSearchAnalyzer("search-1"); - Assert.assertEquals("search-1", stringTermQuery.getSearchAnalyzer()); - - String field1 = "searchTags-1 searchTags.second"; - String stringValue1 = "theValue-1 theValue.second"; - String multiFieldTermQueryJSon = "{\"field\": \"" + field1 + "\", \"value\": \"" + stringValue1 + "\"}"; - TermQuery multiFieldTermQuery = mapper.readValue(multiFieldTermQueryJSon, TermQuery.class); - multiFieldTermQuery.setOperator("and"); - multiFieldTermQuery.setSearchAnalyzer("search-1"); - Assert.assertNotNull(multiFieldTermQuery.toElasticSearch()); - Assert.assertNotNull(multiFieldTermQuery.pathForNestedField(field1)); - - String field2 = "search11 search2"; - String stringValue2 = "theValue1 theValue2"; - String multiFieldTermJSon = "{\"field\": \"" + field2 + "\", \"value\": \"" + stringValue2 + "\"}"; - TermQuery multiFieldTerm = mapper.readValue(multiFieldTermJSon, TermQuery.class); - multiFieldTerm.setOperator("or"); - multiFieldTerm.setSearchAnalyzer("search-1"); - Assert.assertNotNull(multiFieldTerm.toElasticSearch()); - } - -} diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java deleted file mode 100644 index 877b64f..0000000 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/util/ElasticSearchPayloadTranslatorTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 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========================================================= - */ -package org.onap.aai.sa.searchdbabstraction.util; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileInputStream; -import org.apache.commons.io.IOUtils; -import org.junit.Before; -import org.junit.Test; - -public class ElasticSearchPayloadTranslatorTest { - - private final String SIMPLE_DOC_SCHEMA_JSON = "src/test/resources/json/index-mapping.json"; - - @Before - public void setup() throws Exception { - System.setProperty("CONFIG_HOME", System.getProperty("user.dir") + File.separator + "src/test/resources/json"); - } - - @Test - public void testPayloadTranslation() throws Exception { - String expectedErrMsg = "Sample error message for whitespace check"; - File schemaFile = new File(SIMPLE_DOC_SCHEMA_JSON); - String documentJson = IOUtils.toString(new FileInputStream(schemaFile), "UTF-8"); - assertTrue(documentJson.contains("\"type\": \"string\"")); - assertTrue(documentJson.contains("\"index\": \"analyzed\"")); - String translatedPayload = ElasticSearchPayloadTranslator.translateESPayload(documentJson); - assertTrue(translatedPayload.contains("\"type\":\"text\"")); - assertTrue(translatedPayload.contains("\"index\":true")); - assertTrue(translatedPayload.contains("\"fielddata\":true")); - assertFalse(documentJson.contains("\"index\":\"analyzed\"")); - assertTrue(translatedPayload.contains("\"errMsg\":\"" + expectedErrMsg + "\"")); - } -} diff --git a/src/test/resources/json/analysis-config.json b/src/test/resources/json/analysis-config.json deleted file mode 100644 index a622dcf..0000000 --- a/src/test/resources/json/analysis-config.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "name": "nGram_analyzer", - "description": "NGram Analyzer", - "tokenizer": "whitespace", - "filters": [ - "lowercase", - "asciifolding", - "nGram_filter" - ] - }, - { - "name": "whitespace_analyzer", - "description": "Whitespace Analyzer", - "tokenizer": "whitespace", - "filters": [ - "lowercase", - "asciifolding" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/json/bulk-ops-invalid.json b/src/test/resources/json/bulk-ops-invalid.json deleted file mode 100644 index 4708498..0000000 --- a/src/test/resources/json/bulk-ops-invalid.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "operations": [ - { - "operation": "create", - "meta-data": { - "index": "test-index" - }, - "document": { - "field1": "value1", - "field2": "value2" - } - }, - { - "operation": "dance!", - "meta-data": { - "index": "test-index", - "id": "2", - "version": "5" - }, - "document": { - "field1": "new-value" - } - }, - { - "operation": "delete", - "meta-data": { - "index": "test-index", - "id": "4" - } - } - ] -} \ No newline at end of file diff --git a/src/test/resources/json/bulk-ops-valid.json b/src/test/resources/json/bulk-ops-valid.json deleted file mode 100644 index 6e805cf..0000000 --- a/src/test/resources/json/bulk-ops-valid.json +++ /dev/null @@ -1,31 +0,0 @@ -[ - { - "create": { - "metaData": { - "url": "/indexes/test-index/documents/" - }, - "document": { - "field1": "value1", - "field2": "value2" - } - } - }, - { - "update": { - "metaData": { - "url": "/indexes/test-index/documents/3", - "etag": "5" - }, - "document": { - "field1": "new-value" - } - } - }, - { - "delete": { - "metaData": { - "url": "/indexes/test-index/documents/7" - } - } - } -] diff --git a/src/test/resources/json/dynamic-custom-template.json b/src/test/resources/json/dynamic-custom-template.json deleted file mode 100644 index a7bd5ae..0000000 --- a/src/test/resources/json/dynamic-custom-template.json +++ /dev/null @@ -1,12 +0,0 @@ -"dynamic_templates":[ - { - "strings":{ - "match_mapping_type":"string", - "match": "*", - "mapping":{ - "type":"text", - "fielddata":true - } - } - } -], \ No newline at end of file diff --git a/src/test/resources/json/dynamicIndex.json b/src/test/resources/json/dynamicIndex.json deleted file mode 100644 index 5df4069..0000000 --- a/src/test/resources/json/dynamicIndex.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "mappings": { - "dynamic_templates": [{ - "strings": { - "match_mapping_type": "string", - "match": "*", - "mapping": { - "type": "string", - "index": "not_analyzed" - } - } - } - ] - } - - -} \ No newline at end of file diff --git a/src/test/resources/json/es-payload-translation.json b/src/test/resources/json/es-payload-translation.json deleted file mode 100644 index 58ed8f6..0000000 --- a/src/test/resources/json/es-payload-translation.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "attr-translations": [ - { - "query": "$..[?(@.type=='string' && @.index=='analyzed')]", - "update": {"type": "text", "index": true, "fielddata": true} - }, - { - "query": "$..[?(@.type=='string' && @.index=='not_analyzed')]", - "update": {"type": "keyword", "index": true} - }, - { - "query": "$..[?(@.type=='string' && !@.index)]", - "update": {"type": "text", "fielddata": true} - } - ] -} \ No newline at end of file diff --git a/src/test/resources/json/filter-config.json b/src/test/resources/json/filter-config.json deleted file mode 100644 index d1de1d7..0000000 --- a/src/test/resources/json/filter-config.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "name": "nGram_filter", - "description": "Custom NGram Filter.", - "configuration": " \"type\": \"nGram\", \"min_gram\": 1, \"max_gram\": 50, \"token_chars\": [ \"letter\", \"digit\", \"punctuation\", \"symbol\" ]" - } -] \ No newline at end of file diff --git a/src/test/resources/json/index-mapping.json b/src/test/resources/json/index-mapping.json deleted file mode 100644 index e447092..0000000 --- a/src/test/resources/json/index-mapping.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "fields": [ - {"name": "validationId", "type": "string", "searchable": false}, - {"name": "validationTimestamp1", "type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, - {"name": "entityId", "type": "nested"}, - {"name": "entityType", "type": "string", "index": "analyzed"}, - {"name": "entityLink", "type": "string"}, - - {"name": "resourceVersion", "type": "string", "index": "not_analyzed"}, - {"name": "violations", "type": "nested", "sub-fields": [ - {"name": "violationId", "type": "string"}, - {"name": "violationTimestamp", "type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, - {"name": "modelName", "type": "string"}, - {"name": "category", "type": "string"}, - {"name": "severity", "type": "string"}, - {"name": "violationType", "type": "string"}, - {"name": "validationRule", "type": "string"}, - {"name": "violationDetails", "type": "nested", "sub-fields": [ - {"name": "entityId", "type": "nested"}, - {"name": "entityType", "type": "string"}, - {"name": "modelName", "type": "string"}, - {"name": "MISSING_REL", "type": "string"} - ]}, - {"name": "errorMessage", "type": "string", "errMsg": "Sample error message for whitespace check"} - ]} - ] - -} diff --git a/src/test/resources/json/nested-document.json b/src/test/resources/json/nested-document.json deleted file mode 100644 index 8373a6d..0000000 --- a/src/test/resources/json/nested-document.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "fields": [ - { - "name": "serverName", - "data-type": "string", - "searchable": true, - "search-analyzer": "whitespace", - "sub-fields": [] - }, - { - "name": "serverComplex", - "data-type": "string", - "search-analyzer": "whitespace", - "sub-fields": [] - }, - { - "name": "address", - "data-type": "nested", - "sub-fields": [ - { - "name": "street", - "data-type": "string", - "sub-fields": [] - }, - { - "name": "city", - "data-type": "string", - "sub-fields": [] - }, - { - "name": "phone-numbers", - "data-type": "nested", - "sub-fields": [ - { - "name": "home", - "data-type": "string", - "sub-fields": [] - }, - { - "name": "cell", - "data-type": "string", - "sub-fields": [] - } - ] - } - ] - } - ] -} diff --git a/src/test/resources/json/queries/query-with-subrange.json b/src/test/resources/json/queries/query-with-subrange.json deleted file mode 100644 index 36e5f15..0000000 --- a/src/test/resources/json/queries/query-with-subrange.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "results-start": 0, - "results-size": 10, - "queries": [ - { - "must": { - "match": { - "field": "field1", - "value": "Bob" - } - } - } - ] -} \ No newline at end of file diff --git a/src/test/resources/json/queries/simple-parsed-query.json b/src/test/resources/json/queries/simple-parsed-query.json deleted file mode 100644 index 50ce681..0000000 --- a/src/test/resources/json/queries/simple-parsed-query.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "queries": [ - { - "parsed-query": { - "field": "searchTags", - "query-string": "a" - } - } - ] -} \ No newline at end of file diff --git a/src/test/resources/json/search_policy.json b/src/test/resources/json/search_policy.json deleted file mode 100644 index 63c6785..0000000 --- a/src/test/resources/json/search_policy.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "roles": [ - { - "name": "testRole", - "functions": [{ - "name": "testFunction", - "methods": [{ - "name": "GET" - }, { - "name": "DELETE" - }, { - "name": "PUT" - } - ] - } - ], - "users": [{ - "username": "testUser" - } - - ] - }, - - { - "name": "devRole", - "functions": [{ - "name": "search", - "methods": [{ - "name": "GET" - }, { - "name": "DELETE" - }, { - "name": "PUT" - } - ] - } - ], - "users": [ - { - "username": "cn=onap, ou=onap, o=onap, l=ottawa, st=ontario, c=ca" - } - - ] - }, - - { - "name": "testBasicAuth", - "functions": [{ - "name": "testBasicAuthFuncyion", - "methods": [{ - "name": "GET" - } - ] - } - ], - "users": [{ - "user": "testBasicAuthUser", - "pass": "OBF:1ytc1vu91v2p1rxf1mqh1v8s1z0d1msn1san1mqf1z0h1v9u1msl1rvf1v1p1vv11yta" - } - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/json/settings-config.json b/src/test/resources/json/settings-config.json deleted file mode 100644 index 5ebdbcc..0000000 --- a/src/test/resources/json/settings-config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "number_of_shards": "5", - "replication": "TLV_DATACENTER:2", - "drop_on_delete_index": true, - "version": { - "created": "6020399" - } -} - diff --git a/src/test/resources/json/simpleDocument.json b/src/test/resources/json/simpleDocument.json deleted file mode 100644 index c21c574..0000000 --- a/src/test/resources/json/simpleDocument.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "fields": [ - { - "name": "serverName", - "data-type": "string", - "searchable": true, - "search-analyzer": "whitespace", - "sub-fields": [] - }, - { - "name": "serverComplex", - "data-type": "string", - "search-analyzer": "whitespace", - "sub-fields": [] - } - ] -} diff --git a/src/test/resources/json/tier-support-document.json b/src/test/resources/json/tier-support-document.json deleted file mode 100644 index c6a20db..0000000 --- a/src/test/resources/json/tier-support-document.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "document-type": "tier-support", - "document-id": "ts-1", - "fields": [ - { - "name": "entityType", - "data-type": "string" - }, - { - "name": "edgeTagQueryEntityFieldName", - "data-type": "string", - "index": false - }, - { - "name": "edgeTagQueryEntityFieldValue", - "data-type": "string", - "index": false - }, - { - "name": "searchTagIDs", - "data-type": "string" - }, - { - "name": "searchTags", - "data-type": "string", - "index-analyzer": "nGram_analyzer", - "search-analyzer": "whitespace_analyzer" - } - ] -} \ No newline at end of file -- cgit