From fb467c4287de75ea93169732e4f6edfad7616d5a Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 28 May 2020 11:27:08 +0800 Subject: [PATCH 01/17] apply pr: Deliver multiple KeyVault support --- .../pom.xml | 29 +++++++++++++++++++ sdk/spring/azure-spring-boot/pom.xml | 6 ++++ 2 files changed, 35 insertions(+) diff --git a/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml b/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml index 53c97383bd0d..3ae872757e87 100644 --- a/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml +++ b/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml @@ -42,6 +42,35 @@ org.apache.maven.plugins maven-enforcer-plugin 3.0.0-M3 + + + enforce-environment-variable-is-set + + enforce + + + + + AZURE_TENANT + Set the AZURE_TENANT environment variable to your Azure Tenant ID + + + AZURE_SUBSCRIPTION + Set the AZURE_SUBSCRIPTION environment variable to your Azure Subscription ID + + + AZURE_CLIENT_ID + Set the AZURE_CLIENT_ID environment variable to your Application (Client) ID + + + AZURE_CLIENT_SECRET + Set the AZURE_CLIENT_SECRET environment variable to your Application (Client) Secret + + + true + + + diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index f209c269eeb2..663489604b9b 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -250,6 +250,12 @@ 1.1.1 test + + com.azure + azure-identity + 1.0.4 + compile + From 3cd2c7d1c89e431dcefa9c4327cdb03d4963a985 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Tue, 9 Jun 2020 17:30:24 +0800 Subject: [PATCH 02/17] migrate src files from spring-data-cosmosdb --- .../HowToContribute.md | 64 ++ .../QueryPartitionedCollection.md | 58 ++ .../azure-spring-data-cosmosdb/README.md | 335 +++++++++ sdk/spring/azure-spring-data-cosmosdb/pom.xml | 512 +++++++++++++ .../Constants.java | 32 + .../CosmosDbFactory.java | 97 +++ .../common/CosmosdbUtils.java | 65 ++ .../common/ExpressionResolver.java | 40 ++ .../common/MacAddress.java | 146 ++++ .../common/Memoizer.java | 26 + .../common/PropertyLoader.java | 69 ++ .../common/TelemetryEventData.java | 125 ++++ .../common/TelemetrySender.java | 86 +++ .../config/AbstractCosmosConfiguration.java | 57 ++ .../config/CosmosConfigurationSupport.java | 77 ++ .../config/CosmosDBConfig.java | 220 ++++++ .../core/CosmosOperations.java | 90 +++ .../core/CosmosTemplate.java | 627 ++++++++++++++++ .../core/ReactiveCosmosOperations.java | 67 ++ .../core/ReactiveCosmosTemplate.java | 680 ++++++++++++++++++ .../core/ResponseDiagnostics.java | 108 +++ .../core/ResponseDiagnosticsProcessor.java | 21 + .../core/convert/MappingCosmosConverter.java | 176 +++++ .../core/convert/ObjectMapperFactory.java | 27 + .../generator/AbstractQueryGenerator.java | 217 ++++++ .../core/generator/CountQueryGenerator.java | 14 + .../generator/FindQuerySpecGenerator.java | 17 + .../core/generator/QuerySpecGenerator.java | 16 + .../mapping/BasicCosmosPersistentEntity.java | 45 ++ .../BasicCosmosPersistentProperty.java | 36 + .../core/mapping/CosmosMappingContext.java | 39 + .../core/mapping/CosmosPersistentEntity.java | 17 + .../mapping/CosmosPersistentProperty.java | 10 + .../core/mapping/Document.java | 23 + .../core/mapping/DocumentIndexingPolicy.java | 23 + .../core/mapping/PartitionKey.java | 18 + .../core/query/CosmosPageImpl.java | 67 ++ .../core/query/CosmosPageRequest.java | 100 +++ .../core/query/Criteria.java | 62 ++ .../core/query/CriteriaType.java | 191 +++++ .../core/query/DocumentQuery.java | 120 ++++ .../exception/ConfigurationException.java | 16 + .../exception/CosmosDBAccessException.java | 46 ++ .../exception/CosmosDBExceptionUtils.java | 33 + .../exception/DatabaseCreationException.java | 16 + .../exception/IllegalCollectionException.java | 16 + .../exception/IllegalQueryException.java | 16 + .../repository/CosmosRepository.java | 43 ++ .../repository/ReactiveCosmosRepository.java | 38 + .../config/CosmosRepositoriesRegistrar.java | 25 + ...osmosRepositoryConfigurationExtension.java | 75 ++ .../config/EnableCosmosRepositories.java | 45 ++ .../EnableReactiveCosmosRepositories.java | 50 ++ .../ReactiveCosmosRepositoriesRegistrar.java | 25 + ...osmosRepositoryConfigurationExtension.java | 73 ++ .../repository/query/AbstractCosmosQuery.java | 54 ++ .../query/AbstractReactiveCosmosQuery.java | 59 ++ .../query/CosmosEntityMetadata.java | 17 + .../repository/query/CosmosParameter.java | 18 + .../query/CosmosParameterAccessor.java | 9 + .../CosmosParameterParameterAccessor.java | 25 + .../repository/query/CosmosParameters.java | 30 + .../repository/query/CosmosQueryCreator.java | 85 +++ .../query/CosmosQueryExecution.java | 90 +++ .../repository/query/CosmosQueryMethod.java | 31 + .../repository/query/PartTreeCosmosQuery.java | 49 ++ .../query/PartTreeReactiveCosmosQuery.java | 49 ++ .../query/ReactiveCosmosEntityMetadata.java | 12 + .../ReactiveCosmosParameterAccessor.java | 9 + ...ctiveCosmosParameterParameterAccessor.java | 25 + .../query/ReactiveCosmosQueryCreator.java | 82 +++ .../query/ReactiveCosmosQueryExecution.java | 66 ++ .../query/ReactiveCosmosQueryMethod.java | 31 + .../query/SimpleCosmosEntityMetadata.java | 32 + .../SimpleReactiveCosmosEntityMetadata.java | 34 + .../support/CosmosEntityInformation.java | 283 ++++++++ .../support/CosmosRepositoryFactory.java | 77 ++ .../support/CosmosRepositoryFactoryBean.java | 69 ++ .../ReactiveCosmosRepositoryFactory.java | 82 +++ .../ReactiveCosmosRepositoryFactoryBean.java | 69 ++ .../support/SimpleCosmosRepository.java | 268 +++++++ .../SimpleReactiveCosmosRepository.java | 227 ++++++ .../resources/META-INF/project.properties | 1 + .../main/resources/META-INF/spring.factories | 1 + .../src/main/resources/telemetry.config | 1 + sdk/spring/pom.xml | 1 + 86 files changed, 7223 insertions(+) create mode 100644 sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md create mode 100644 sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md create mode 100644 sdk/spring/azure-spring-data-cosmosdb/README.md create mode 100644 sdk/spring/azure-spring-data-cosmosdb/pom.xml create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config diff --git a/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md b/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md new file mode 100644 index 000000000000..ea1355c840b5 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md @@ -0,0 +1,64 @@ +# How to Build and Contribute +This instruction is guideline for building and code contribution. + +## Prequisites +- JDK 1.8 and above +- [Maven](http://maven.apache.org/) 3.0 and above + +## Build from source +To build the project, run maven commands. + +```bash +git clone https://github.com/Microsoft/spring-data-cosmosdb.git +cd spring-data-cosmosdb +mvnw clean install +``` + +## Test +There're 3 profiles: `dev`, `integration-test-azure` and `integration-test-emulator`. Default profile is `dev`. Profile `integration-test-azure` will trigger integration test execution against Azure Cosmos DB. Profile `integration-test-emulator` will trigger integration test execution against [Azure Cosmos DB Emulator](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator), you need to follow the link to setup emulator before test execution. + +- Run unit tests +```bash +mvnw clean install +``` + +- Run integration tests + - on Azure + >**NOTE** Please note that integration test against Azure will automatically create a Azure Cosmos DB Document API in your Azure subscription, then there will be **Azure usage fee.** + + Integration tests will require a Azure Subscription. If you don't already have an Azure subscription, you can activate your [MSDN subscriber benefits](https://azure.microsoft.com/en-us/pricing/member-offers/msdn-benefits-details/) or sign up for a [free Azure account](https://azure.microsoft.com/en-us/free/). + + 1. Create a service principal by using Azure Cli or by [Azure Portal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal). + 2. After service principal ready, set environment variables CLIENT_ID, CLIENT_KEY and TENANT_ID, where value of them are service principal id, key and tenant id. + 3. Run maven command with `integration-test-azure` profile. + + ```bash + set CLIENT_ID=your-azure-service-principal-id + set CLIENT_KEY=your-azure-service-principal-key + set TENANT_ID=your-azure-subscription-tenant-id + mvnw -P integration-test-azure clean install + ``` + - on Emulator + + Setup Azure Cosmos DB Emulator by following [this instruction](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator), then run test with: + ```bash + mvnw -P integration-test-emulator install + ``` + + +- Skip tests execution +```bash +mvnw clean install -DskipTests +``` + +## Version management +Developing version naming convention is like `0.1.2-SNAPSHOT`. Release version naming convention is like `0.1.2`. + +## CI +Both [travis](https://travis-ci.org/Microsoft/spring-data-cosmosdb) and [appveyor](https://ci.appveyor.com/project/yungez/spring-data-cosmosdb) CI is enabled. + +## Contribute to code +Code contribution is welcome. To contribute to this module, please make sure below check list are checked. +- [ ] Build pass. checkstyle and findbugs is enabled by default. Please check [checkstyle.xml](config/checkstyle.xml) to learn detail checkstyle configuration. +- [ ] Documents are updated to align with code. +- [ ] Code coverage for new codes >= 65%. Code coverage check is enabled with 65% bar. diff --git a/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md b/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md new file mode 100644 index 000000000000..1c0d04129e7d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md @@ -0,0 +1,58 @@ +### How to Query Partitioned Azure Cosmos DB Collection + +With Azure Cosmos DB, you can configure [partition key](https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data) for your collection. + +Below is an example about how to query partitioned collection with this spring data module. + +#### Example + +Given a document entity structure: +``` + @Document + @Data + @AllArgsConstructor + public class Address { + @Id + String postalCode; + String street; + @PartitionKey + String city; + } +``` + +Write the repository interface: +``` + @Repository + public interface AddressRepository extends DocumentDbRepository { + // Add query methods here, refer to below + } +``` + +Query by field name: +``` + List
findByCity(String city); +``` + +Delete by field name: +``` + void deleteByStreet(String street); +``` + +For `Partitioned collection`, if you want to query records by `findById(id)`, exception will be thrown. +``` + // Incorrect for partitioned collection, exception will be thrown + Address result = repository.findById(id); // Caution: Works for non-partitioned collection +``` + +Instead, you can query records by ID field name with custom query. +``` + // Correct, postalCode is the ID field in Address domain + @Repository + public interface AddressRepository extends DocumentDbRepository { + List
findByPostalCode(String postalCode); + } + + // Query + List
result = repository.findByPostalCode(postalCode); +``` + diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/spring/azure-spring-data-cosmosdb/README.md new file mode 100644 index 000000000000..849a8e3ed4b2 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/README.md @@ -0,0 +1,335 @@ +[![Travis CI](https://travis-ci.org/Microsoft/spring-data-cosmosdb.svg?branch=master)](https://travis-ci.org/Microsoft/spring-data-cosmosdb) +[![codecov](https://codecov.io/gh/Microsoft/spring-data-cosmosdb/branch/master/graph/badge.svg)](https://codecov.io/gh/Microsoft/spring-data-cosmosdb) +[![MIT License](http://img.shields.io/badge/license-MIT-green.svg) ](https://github.com/Microsoft/spring-data-cosmosdb/blob/master/LICENSE) + + +# Spring Data for Azure Cosmos DB + +[Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction) is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as SQL, MongoDB, Cassandra, Graph, and Table. + +**Spring Data Azure Cosmos DB** provides initial Spring Data support for Azure Cosmos DB using the [SQL API](https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-introduction), based on Spring Data framework. Currently it only supports SQL API, the other APIs are in the plan. + +## TOC + +* [Sample Code](#sample-code) +* [Spring data version support](#spring-data-version-support) +* [Feature List](#feature-list) +* [Quick Start](#quick-start) +* [Query Partitioned Collection](QueryPartitionedCollection.md) +* [Snapshots](#snapshots) +* [Filing Issues](#filing-issues) +* [How to Contribute](#how-to-contribute) +* [Code of Conduct](#code-of-conduct) + +## Sample Code +Please refer to [sample project here](./samplecode). + +## Spring Data Version Support +Version mapping between spring boot and spring-data-cosmosdb: + +| Spring boot version | spring-data-cosmosdb version | +| :----------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| ![version](https://img.shields.io/badge/version-2.3.x-blue) | [![Maven Central](https://img.shields.io/maven-central/v/com.microsoft.azure/spring-data-cosmosdb/2.3.svg)](https://search.maven.org/search?q=g:com.microsoft.azure%20AND%20a:spring-data-cosmosdb%20AND%20v:2.3.*) | +| ![version](https://img.shields.io/badge/version-2.2.x-blue) | [![Maven Central](https://img.shields.io/maven-central/v/com.microsoft.azure/spring-data-cosmosdb/2.2.svg)](https://search.maven.org/search?q=g:com.microsoft.azure%20AND%20a:spring-data-cosmosdb%20AND%20v:2.2.*) | +| ![version](https://img.shields.io/badge/version-2.1.x-blue) | [![Maven Central](https://img.shields.io/maven-central/v/com.microsoft.azure/spring-data-cosmosdb/2.1.svg)](https://search.maven.org/search?q=g:com.microsoft.azure%20AND%20a:spring-data-cosmosdb%20AND%20v:2.1.*) | +| ![version](https://img.shields.io/badge/version-2.0.x-blue) | [![Maven Central](https://img.shields.io/maven-central/v/com.microsoft.azure/spring-data-cosmosdb/2.0.svg)](https://search.maven.org/search?q=g:com.microsoft.azure%20AND%20a:spring-data-cosmosdb%20AND%20v:2.0.*) | + +## Feature List +- Spring Data ReactiveCrudRepository CrudRepository basic CRUD functionality + - save + - findAll + - findOne by Id + - deleteAll + - delete by Id + - delete entity +- Spring Data [@Id](https://github.com/spring-projects/spring-data-commons/blob/db62390de90c93a78743c97cc2cc9ccd964994a5/src/main/java/org/springframework/data/annotation/Id.java) annotation. + There're 2 ways to map a field in domain class to `id` field of Azure Cosmos DB document. + - annotate a field in domain class with `@Id`, this field will be mapped to document `id` in Cosmos DB. + - set name of this field to `id`, this field will be mapped to document `id` in Azure Cosmos DB. +- Custom collection Name. + By default, collection name will be class name of user domain class. To customize it, add the `@Document(collection="myCustomCollectionName")` annotation to the domain class. The collection field also supports SpEL expressions (eg. `collection = "${dynamic.collection.name}"` or `collection = "#{@someBean.getContainerName()}"`) in order to provide collection names programmatically/via configuration properties. +- Custom IndexingPolicy + By default, IndexingPolicy will be set by azure service. To customize it add annotation `@DocumentIndexingPolicy` to domain class. This annotation has 4 attributes to customize, see following: +```java + boolean automatic; // Indicate if indexing policy use automatic or not + IndexingMode mode; // Indexing policy mode, option Consistent|Lazy|None. + String[] includePaths; // Included paths for indexing + String[] excludePaths; // Excluded paths for indexing +``` +- Supports Optimistic Locking for specific collections, which means upserts/deletes by document will fail with an exception in case the document was modified by another process in the meanwhile. To enable Optimistic Locking for a collection, just create a string `_etag` field and mark it with the `@Version` annotation. See the following: + +```java +@Document(collection = "myCollection") +class MyDocument { + String id; + String data; + @Version + String _etag; +} +``` +- Supports [Azure Cosmos DB partition](https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data). To specify a field of domain class to be partition key field, just annotate it with `@PartitionKey`. When you do CRUD operation, pls specify your partition value. For more sample on partition CRUD, pls refer to [test here](./src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/integration/AddressRepositoryIT.java) +- Supports [Spring Data custom query](https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.query-methods.details) find operation, e.g., `findByAFieldAndBField` +- Supports [Spring Data pagable and sort](https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.special-parameters). + - Based on available RUs on the database account, cosmosDB can return documents less than or equal to the requested size. + - Due to this variable number of returned documents in every iteration, user should not rely on the totalPageSize, and instead iterating over pageable should be done in this way. +```java + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null); + Page page = tRepository.findAll(pageRequest); + List pageContent = page.getContent(); + while(page.hasNext()) { + Pageable nextPageable = page.nextPageable(); + page = repository.findAll(nextPageable); + pageContent = page.getContent(); + } +``` +- Supports [spring-boot-starter-data-rest](https://projects.spring.io/spring-data-rest/). +- Supports List and nested type in domain class. +- Configurable ObjectMapper bean with unique name `cosmosdbObjectMapper`, only configure customized ObjectMapper if you really need to. e.g., +```java + @Bean(name = "cosmosdbObjectMapper") + public ObjectMapper objectMapper() { + return new ObjectMapper(); // Do configuration to the ObjectMapper if required + } +``` + +## Quick Start + +### Add the dependency +`spring-data-cosmosdb` is published on Maven Central Repository. +If you are using Maven, add the following dependency. + +```xml + + com.microsoft.azure + spring-data-cosmosdb + 2.2.4 + +``` + +### Setup Configuration +Setup configuration class. + +CosmosKeyCredential feature provides capability to rotate keys on the fly. You can switch keys using switchToSecondaryKey(). +For more information on this, see the Sample Application code. + +### Sync and Reactive Repository support +2.2.x supports both sync and reactive repository support. + +Use `@EnableCosmosRepositories` to enable sync repository support. + +For reactive repository support, use `@EnableReactiveCosmosRepositories` + +### Response Diagnostics String and Query Metrics +2.2.x supports Response Diagnostics String and Query Metrics. +Set `populateQueryMetrics` flag to true in application.properties to enable query metrics. +In addition to setting the flag, implement `ResponseDiagnosticsProcessor` to log diagnostics information. + +```java +@Configuration +@EnableCosmosRepositories +@Slf4j +public class AppConfiguration extends AbstractCosmosConfiguration { + + @Value("${azure.cosmosdb.uri}") + private String uri; + + @Value("${azure.cosmosdb.key}") + private String key; + + @Value("${azure.cosmosdb.secondaryKey}") + private String secondaryKey; + + @Value("${azure.cosmosdb.database}") + private String dbName; + + @Value("${azure.cosmosdb.populateQueryMetrics}") + private boolean populateQueryMetrics; + + private CosmosKeyCredential cosmosKeyCredential; + + public CosmosDBConfig getConfig() { + this.cosmosKeyCredential = new CosmosKeyCredential(key); + CosmosDbConfig cosmosdbConfig = CosmosDBConfig.builder(uri, + this.cosmosKeyCredential, dbName).build(); + cosmosdbConfig.setPopulateQueryMetrics(populateQueryMetrics); + cosmosdbConfig.setResponseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation()); + return cosmosdbConfig; + } + + public void switchToSecondaryKey() { + this.cosmosKeyCredential.key(secondaryKey); + } + + private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor { + + @Override + public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) { + log.info("Response Diagnostics {}", responseDiagnostics); + } + } + +} +``` +Or if you want to customize your config: +```java +public CosmosDBConfig getConfig() { + this.cosmosKeyCredential = new CosmosKeyCredential(key); + CosmosDBConfig cosmosDbConfig = CosmosDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build(); + cosmosDbConfig.getConnectionPolicy().setConnectionMode(ConnectionMode.DIRECT); + cosmosDbConfig.getConnectionPolicy().setMaxPoolSize(1000); + return cosmosDbConfig; +} +``` +By default, `@EnableCosmosRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories. +```java +@Configuration +@EnableCosmosRepositories(basePackageClass=UserRepository.class) +public class AppConfiguration extends AbstractCosmosConfiguration { + // configuration code +} +``` + + +### Define an entity +Define a simple entity as Document in Azure Cosmos DB. + +You can define entities by adding the `@Document` annotation and specifying properties related to the container, such as the container name, request units (RUs), time to live, and auto-create container. + +Containers are created automatically unless you don't want them to: Set `autoCreateCollection` to false in `@Document` annotation to disable auto creation of containers. + +Note: By default request units assigned to newly created containers is 4000. Specify different ru value to customize request units for container created by the SDK (minimum RU value is 400). + +```java +@Document(collection = "myCollection", ru = "400") +public class User { + private String id; + private String firstName; + + @PartitionKey + private String lastName; + + ... // setters and getters + + public User() { + // If you do not want to create a default constructor, + // use annotation @JsonCreator and @JsonProperty in the full args constructor + } + + public User(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("User: %s %s, %s", firstName, lastName, id); + } +} +``` +`id` field will be used as document id in Azure Cosmos DB. If you want use another field like `emailAddress` as document `id`, just annotate that field with `@Id` annotation. + +Annotation `@Document(collection="mycollection")` is used to specify collection name in Azure Cosmos DB. +Annotation `@PartitionKey` on `lastName` field is used to specify this field be partition key in Azure Cosmos DB. + +```java +@Document(collection = "mycollection") +public class User { + @Id + private String emailAddress; + + ... +} +``` + +### Create repositories +Extends CosmosRepository interface, which provides Spring Data repository support. + +```java +import CosmosRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends CosmosRepository { + List findByFirstName(String firstName); +} +``` + +`findByFirstName` method is custom query method, it will find documents per FirstName. + +### Create an Application class +Here create an application class with all the components + +```java +@SpringBootApplication +public class SampleApplication implements CommandLineRunner { + + @Autowired + private UserRepository repository; + + @Autowired + private ApplicationContext applicationContext; + + public static void main(String[] args) { + SpringApplication.run(SampleApplication.class, args); + } + + public void run(String... var1) throws Exception { + + final User testUser = new User("testId", "testFirstName", "testLastName"); + + repository.deleteAll(); + repository.save(testUser); + + // to find by Id, please specify partition key value if collection is partitioned + final User result = repository.findOne(testUser.getId(), testUser.getLastName); + // if emailAddress is mapped to id, then + // final User result = respository.findOne(testUser.getEmailAddress(), testUser.getLastName()); + + // Switch to secondary key + UserRepositoryConfiguration bean = + applicationContext.getBean(UserRepositoryConfiguration.class); + bean.switchToSecondaryKey(); + + // Now repository will use secondary key + repository.save(testUser); + + } +} +``` +Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the CosmosTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries. + +## Snapshots +[![Nexus OSS](https://img.shields.io/nexus/snapshots/https/oss.sonatype.org/com.microsoft.azure/spring-data-cosmosdb.svg)](https://oss.sonatype.org/content/repositories/snapshots/com/microsoft/azure/spring-data-cosmosdb/) + +Snapshots built from `master` branch are available, add [maven repositories](https://maven.apache.org/settings.html#Repositories) configuration to your pom file as below. +```xml + + + nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + true + always + + + +``` + +## Filing Issues + +If you encounter any bug, please file an issue [here](https://github.com/Microsoft/spring-data-cosmosdb/issues/new). + +To suggest a new feature or changes that could be made, file an issue the same way you would for a bug. + +## How To Contribute + +Contribution is welcome. Please follow [this instruction](./HowToContribute.md) to contribute code. + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +### Data/Telemetry + + This project collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy](https://privacy.microsoft.com/en-us/privacystatement) statement to learn more. diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml new file mode 100644 index 000000000000..2cabdd5c3aa6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -0,0 +1,512 @@ + + + 4.0.0 + + com.microsoft.azure + spring-data-cosmosdb + 2.3.1-SNAPSHOT + + Spring Data for Azure Cosmos DB SQL API + Spring Data for Azure Cosmos DB SQL API + https://github.com/Microsoft/spring-data-cosmosdb + + + + MIT + https://github.com/Microsoft/spring-data-cosmosdb/blob/master/LICENSE + repo + + + + + + yungez + Yunge Zhu + yungez@microsoft.com + + + + + Microsoft + https://www.microsoft.com + + + + scm:git:git://github.com/Microsoft/spring-data-cosmosdb.git + scm:git:ssh://github.com:Microsoft/spring-data-cosmosdb.git + + https://github.com/Microsoft/spring-data-cosmosdb/tree/master + + + 1.8 + 1.8 + UTF-8 + MM-dd-HH-mm-ss + + 5.2.6.RELEASE + 2.3.0.RELEASE + 2.10.0 + + 2.8.9 + 1.7.1 + 2.3.0.RELEASE + 1.2 + 1.7.25 + 2.8.4 + 3.3.0.RELEASE + + 3.7.3 + spring-data-cosmosdb-test + testdb-${maven.build.timestamp} + true + false + false + + + + + spring-milestone + Spring Milestones + https://repo.spring.io/libs-milestone + + + + + + org.springframework + spring-core + ${spring.springframework.version} + + + commons-logging + commons-logging + + + + + + org.springframework + spring-web + ${spring.springframework.version} + + + + org.springframework + spring-beans + ${spring.springframework.version} + + + + org.springframework + spring-context + ${spring.springframework.version} + + + + org.springframework + spring-tx + ${spring.springframework.version} + + + + org.springframework.data + spring-data-commons + ${spring.data.version} + + + + org.springframework + spring-expression + ${spring.springframework.version} + + + com.microsoft.azure + azure-cosmos + ${azure.cosmos.version} + + + + com.fasterxml.jackson.module + jackson-module-parameter-names + ${fasterxml.jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${fasterxml.jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${fasterxml.jackson.version} + + + org.json + json + 20140107 + + + + org.javatuples + javatuples + ${java.tuples.version} + + + + + org.mockito + mockito-core + ${mockito.core.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.starter.test.version} + test + + + com.vaadin.external.google + android-json + + + + + + io.projectreactor + reactor-test + ${project.reactor.test.version} + test + + + + org.slf4j + slf4j-simple + ${slf4j.version} + test + + + + com.google.code.gson + gson + ${gson.version} + test + + + + + + + src/main/resources + true + + META-INF/project.properties + telemetry.config + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + private + false + + + com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicCosmosPersistentProperty.java + + + + + + attach-javadocs + + jar + + + ${javadoc.opts} + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + validate + validate + + ${project.basedir}/config/checkstyle.xml + UTF-8 + true + true + true + true + + + check + + + + + false + + true + + + + org.apache.maven.plugins + maven-help-plugin + 3.1.0 + + + show-profiles + compile + + active-profiles + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + Max + Low + true + ${project.build.directory}/findbugs + + ${project.basedir}/config/findbugs-exclude.xml + + + + org.apache.ant + ant + 1.9.4 + + + + + compile + + check + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + true + 65 + 65 + + + + com/microsoft/azure/**/GetHashMac.class + com/microsoft/azure/**/Constants.class + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19 + + src/test/resources/application.properties + ${skip.integration.tests} + + + + integration-test + + integration-test + verify + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + setup + pre-integration-test + + run + + + + + + + + + + + cleanup + post-integration-test + + run + + + + + + + + + + + + + + + dev + + true + + + dev + true + false + false + + + + integration-test-azure + + integration-test-azure + false + true + false + + + + travis-ci-test + + travis-ci-test + false + true + false + + + + performance-test + + performance-test + false + false + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + PerformanceCompare.java + + + + + + + + integration-test-emulator + + integration-test-emulator + false + false + true + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + **/PageablePersonRepositoryIT.java + + + + + + + + release + + + release + + + + + doclint-java8-disable + + [1.8,) + + + -Xdoclint:none + + + + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java new file mode 100644 index 000000000000..0224180f4032 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb; + +import com.azure.data.cosmos.IndexingMode; + +public class Constants { + + public static final String DEFAULT_COLLECTION_NAME = ""; + public static final String DEFAULT_REQUEST_UNIT = "4000"; + public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true; + public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT; + public static final String DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX = "Impl"; + public static final int DEFAULT_TIME_TO_LIVE = -1; // Indicates never expire + public static final boolean DEFAULT_AUTO_CREATE_CONTAINER = true; + + public static final String ID_PROPERTY_NAME = "id"; + + public static final String COSMOSDB_MODULE_NAME = "cosmosdb"; + public static final String COSMOSDB_MODULE_PREFIX = "cosmosdb"; + public static final String COSMOS_MAPPING_CONTEXT = "cosmosMappingContext"; + + public static final String USER_AGENT_SUFFIX = "spring-data/"; + + public static final String OBJECTMAPPER_BEAN_NAME = "cosmosdbObjectMapper"; + + public static final String ISO_8601_COMPATIBLE_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss:SSSXXX"; + + private Constants() { + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java new file mode 100644 index 000000000000..bc5c83c48a4f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb; + +import com.azure.data.cosmos.ConnectionPolicy; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.sync.CosmosSyncClient; +import com.microsoft.azure.spring.data.cosmosdb.common.MacAddress; +import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader; +import com.microsoft.azure.spring.data.cosmosdb.common.TelemetrySender; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import org.springframework.lang.NonNull; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import javax.annotation.PostConstruct; + +public class CosmosDbFactory { + + private final CosmosDBConfig config; + + private static final boolean IS_TELEMETRY_ALLOWED = PropertyLoader.isApplicationTelemetryAllowed(); + + private static final String USER_AGENT_SUFFIX = Constants.USER_AGENT_SUFFIX + PropertyLoader.getProjectVersion(); + + private String getUserAgentSuffix() { + String suffix = ";" + USER_AGENT_SUFFIX; + + if (IS_TELEMETRY_ALLOWED || config.isAllowTelemetry()) { + suffix += ";" + MacAddress.getHashMac(); + } + + return suffix; + } + + public CosmosDbFactory(@NonNull CosmosDBConfig config) { + validateConfig(config); + + this.config = config; + } + + public CosmosClient getCosmosClient() { + final ConnectionPolicy policy = config.getConnectionPolicy(); + final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix(); + + policy.userAgentSuffix(userAgent); + return CosmosClient.builder() + .endpoint(config.getUri()) + .key(config.getKey()) + .cosmosKeyCredential(config.getCosmosKeyCredential()) + .connectionPolicy(policy) + .consistencyLevel(config.getConsistencyLevel()) + .build(); + } + + public CosmosSyncClient getCosmosSyncClient() { + final ConnectionPolicy policy = config.getConnectionPolicy(); + final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix(); + + policy.userAgentSuffix(userAgent); + return CosmosClient.builder() + .endpoint(config.getUri()) + .key(config.getKey()) + .cosmosKeyCredential(config.getCosmosKeyCredential()) + .connectionPolicy(policy) + .consistencyLevel(config.getConsistencyLevel()) + .buildSyncClient(); + } + + private void validateConfig(@NonNull CosmosDBConfig config) { + Assert.hasText(config.getUri(), "cosmosdb host url should have text!"); + if (config.getCosmosKeyCredential() == null) { + Assert.hasText(config.getKey(), "cosmosdb host key should have text!"); + } else if (StringUtils.isEmpty(config.getKey())) { + Assert.hasText(config.getCosmosKeyCredential().key(), + "cosmosdb credential host key should have text!"); + } + Assert.hasText(config.getDatabase(), "cosmosdb database should have text!"); + Assert.notNull(config.getConnectionPolicy(), "cosmosdb connection policy should not be null!"); + } + + @PostConstruct + private void sendTelemetry() { + // If any one of them is enabled, send telemetry data + if (IS_TELEMETRY_ALLOWED || config.isAllowTelemetry()) { + final TelemetrySender sender = new TelemetrySender(); + + sender.send(this.getClass().getSimpleName()); + } + } + + public CosmosDBConfig getConfig() { + return config; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java new file mode 100644 index 000000000000..dac7ec510999 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.azure.data.cosmos.CosmosResponse; +import com.azure.data.cosmos.CosmosResponseDiagnostics; +import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.FeedResponseDiagnostics; +import com.azure.data.cosmos.Resource; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnostics; +import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnosticsProcessor; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.ObjectMapperFactory; +import com.microsoft.azure.spring.data.cosmosdb.exception.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; + +import java.io.IOException; + +public class CosmosdbUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(CosmosdbUtils.class); + + @SuppressWarnings("unchecked") + public static T getCopyFrom(@NonNull T instance) { + final ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); + + try { + final String s = mapper.writeValueAsString(instance); + return (T) mapper.readValue(s, instance.getClass()); + } catch (IOException e) { + throw new ConfigurationException("failed to get copy from " + instance.getClass().getName(), e); + } + } + + public static void fillAndProcessResponseDiagnostics( + ResponseDiagnosticsProcessor responseDiagnosticsProcessor, + CosmosResponse cosmosResponse, FeedResponse feedResponse) { + if (responseDiagnosticsProcessor == null) { + return; + } + CosmosResponseDiagnostics cosmosResponseDiagnostics = null; + if (cosmosResponse != null) { + cosmosResponseDiagnostics = cosmosResponse.cosmosResponseDiagnosticsString(); + } + FeedResponseDiagnostics feedResponseDiagnostics = null; + ResponseDiagnostics.CosmosResponseStatistics cosmosResponseStatistics = null; + if (feedResponse != null) { + feedResponseDiagnostics = feedResponse.feedResponseDiagnostics(); + cosmosResponseStatistics = new ResponseDiagnostics.CosmosResponseStatistics(feedResponse); + } + if (cosmosResponseDiagnostics == null && + (feedResponseDiagnostics == null || feedResponseDiagnostics.toString().isEmpty()) && + cosmosResponseStatistics == null) { + LOGGER.debug("Empty response diagnostics"); + return; + } + final ResponseDiagnostics responseDiagnostics = + new ResponseDiagnostics(cosmosResponseDiagnostics, feedResponseDiagnostics, cosmosResponseStatistics); + + // Process response diagnostics + responseDiagnosticsProcessor.processResponseDiagnostics(responseDiagnostics); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java new file mode 100644 index 000000000000..2df771685b19 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.config.EmbeddedValueResolver; + +/** + * + * @author Domenico Sibilio + * + */ +public class ExpressionResolver { + + private static EmbeddedValueResolver embeddedValueResolver; + + public ExpressionResolver(BeanFactory beanFactory) { + if (beanFactory instanceof ConfigurableBeanFactory) { + setEmbeddedValueResolver(new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory)); + } + } + + /** + * Resolve the given string value via an {@link EmbeddedValueResolver} + * @param expression the expression to be resolved + * @return the resolved expression, may be {@literal null} + */ + public static String resolveExpression(String expression) { + return embeddedValueResolver != null + ? embeddedValueResolver.resolveStringValue(expression) + : expression; + } + + private static void setEmbeddedValueResolver(EmbeddedValueResolver embeddedValueResolver) { + ExpressionResolver.embeddedValueResolver = embeddedValueResolver; + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java new file mode 100644 index 000000000000..90411d5ce4fb --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +/* + * Disclaimer: + * This class is copied from https://github.com/Microsoft/azure-tools-for-java/ with minor modification (fixing + * static analysis error). + * Location in the repo: /Utils/azuretools-core/src/com/microsoft/azuretools/azurecommons/util/MacAddress.java + */ + +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MacAddress { + + private static final String UNKNOWN_MAC_ADDRESS = "Unknown-Mac-Address"; + private static final String MAC_REGEX = "([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}"; + private static final String MAC_REGEX_ZERO = "([0]{2}[:-]){5}[0]{2}"; + private static final String HASHED_MAC_REGEX = "[0-9a-f]{64}"; + + private MacAddress() { + } + + private static boolean isValidHashMacFormat(@NonNull String hashMac) { + if (hashMac.isEmpty()) { + return false; + } + + return Pattern.compile(HASHED_MAC_REGEX).matcher(hashMac).matches(); + } + + private static String getRawMac() { + final List commands; + final String os = System.getProperty("os.name"); + final StringBuilder macBuilder = new StringBuilder(); + + if (os != null && !os.isEmpty() && os.toLowerCase(Locale.US).startsWith("win")) { + commands = Collections.singletonList("getmac"); + } else { + commands = Arrays.asList("ifconfig", "-a"); + } + + try { + String tmp; + final ProcessBuilder builder = new ProcessBuilder(commands); + final Process process = builder.start(); + final InputStreamReader streamReader = new InputStreamReader(process.getInputStream(), + StandardCharsets.UTF_8); + + try { + final BufferedReader reader = new BufferedReader(streamReader); + try { + while ((tmp = reader.readLine()) != null) { + macBuilder.append(tmp); + } + } finally { + reader.close(); + } + } finally { + streamReader.close(); + } + } catch (IOException e) { + return ""; + } + + return macBuilder.toString(); + } + + private static String getHexDigest(byte digest) { + final String hex = Integer.toString((digest & 0xff) + 0x100, 16); + + return hex.substring(1); + } + + private static String hash(@NonNull String mac) { + if (mac.isEmpty()) { + return ""; + } + + final StringBuilder builder = new StringBuilder(); + + try { + final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); + + messageDigest.update(mac.getBytes(StandardCharsets.UTF_8)); + + final byte[] digestBytes = messageDigest.digest(); + + for (final byte digest : digestBytes) { + builder.append(getHexDigest(digest)); + } + } catch (NoSuchAlgorithmException ex) { + return ""; + } + + Assert.isTrue(isValidHashMacFormat(builder.toString()), "Invalid format for HashMac"); + + return builder.toString(); + } + + public static String getHashMac() { + final String rawMac = getRawMac(); + + if (rawMac.isEmpty()) { + return UNKNOWN_MAC_ADDRESS; + } + + final Pattern pattern = Pattern.compile(MAC_REGEX); + final Pattern patternZero = Pattern.compile(MAC_REGEX_ZERO); + final Matcher matcher = pattern.matcher(rawMac); + + String mac = ""; + + while (matcher.find()) { + mac = matcher.group(0); + + if (!patternZero.matcher(mac).matches()) { + break; + } + } + + final String hashMac = hash(mac); + + if (StringUtils.hasText(hashMac)) { + return hashMac; + } + + return UNKNOWN_MAC_ADDRESS; + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java new file mode 100644 index 000000000000..f0af790208d3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +/** + * Memoize function computation results + */ +public class Memoizer { + + private final Map cache = new ConcurrentHashMap<>(); + + private Memoizer() {} + + public static Function memoize(Function function) { + return new Memoizer().internalMemoize(function); + } + + private Function internalMemoize(Function function) { + return input -> cache.computeIfAbsent(input, function); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java new file mode 100644 index 000000000000..6e1bfbd30c1e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.springframework.lang.NonNull; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class PropertyLoader { + + private static final String PROJECT_PROPERTY_FILE = "/META-INF/project.properties"; + + private static final String APPLICATION_PROPERTY_FILE = "/application.properties"; + + private static final String APPLICATION_YML_FILE = "/application.yml"; + + private static final String TELEMETRY_CONFIG_FILE = "/telemetry.config"; + + private PropertyLoader() { + } + + public static String getProjectVersion() { + return getPropertyByName("project.version", PROJECT_PROPERTY_FILE); + } + + public static String getTelemetryInstrumentationKey() { + return getPropertyByName("telemetry.instrumentationKey", TELEMETRY_CONFIG_FILE); + } + + public static boolean isApplicationTelemetryAllowed() { + String allowed = getPropertyByName("cosmosdb.telemetryAllowed", APPLICATION_PROPERTY_FILE); + + if (allowed == null) { + allowed = getPropertyByName("telemetryAllowed", APPLICATION_YML_FILE); + } + + // Default, no telemetry + if (allowed == null) { + return false; + } else { + return !allowed.equalsIgnoreCase("false"); + } + } + + private static String getPropertyByName(@NonNull String name, @NonNull String filename) { + final Properties properties = new Properties(); + final InputStream inputStream = PropertyLoader.class.getResourceAsStream(filename); + + if (inputStream == null) { + return null; + } + + try { + properties.load(inputStream); + } catch (IOException e) { + // Omitted + } finally { + try { + inputStream.close(); + } catch (IOException e) { + // Omitted + } + } + + return properties.getProperty(name); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java new file mode 100644 index 000000000000..48d041b8f531 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import java.time.Instant; +import java.util.Map; + +public class TelemetryEventData { + + private final String name; + + @JsonProperty("iKey") + private final String instrumentationKey; + + private final Tags tags = new Tags("Spring-on-azure", "Java-maven-plugin"); + + private final EventData data = new EventData("EventData"); + + private final String time; + + public TelemetryEventData(String eventName, @NonNull Map properties) { + Assert.hasText(eventName, "Event name should contain text."); + + name = "Microsoft.ApplicationInsights.Event"; + instrumentationKey = PropertyLoader.getTelemetryInstrumentationKey(); + + data.getBaseData().setName(eventName); + data.getBaseData().setProperties(properties); + time = Instant.now().toString(); + } + + public String getName() { + return name; + } + + public String getInstrumentationKey() { + return instrumentationKey; + } + + public Tags getTags() { + return tags; + } + + public EventData getData() { + return data; + } + + public String getTime() { + return time; + } + + private static class Tags { + + @JsonProperty("ai.cloud.roleInstance") + private final String aiCloudRoleInstance; + + @JsonProperty("ai.internal.sdkVersion") + private final String aiInternalSdkVersion; + + public Tags(String instance, String sdkVersion) { + aiCloudRoleInstance = instance; + aiInternalSdkVersion = sdkVersion; + } + + public String getAiCloudRoleInstance() { + return aiCloudRoleInstance; + } + + public String getAiInternalSdkVersion() { + return aiInternalSdkVersion; + } + } + + private static class EventData { + + private final String baseType; + + private final CustomData baseData = new CustomData(); + + public EventData(String baseType) { + this.baseType = baseType; + } + + public String getBaseType() { + return baseType; + } + + public CustomData getBaseData() { + return baseData; + } + + private static class CustomData { + + private final Integer ver = 2; + + private String name; + + private Map properties; + + public Integer getVer() { + return ver; + } + + public String getName() { + return name; + } + + private void setName(String name) { + this.name = name; + } + + public Map getProperties() { + return properties; + } + + private void setProperties(Map properties) { + this.properties = properties; + } + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java new file mode 100644 index 000000000000..3ccf9731323c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.http.*; +import org.springframework.util.Assert; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON; + +public class TelemetrySender { + + private static final Logger LOGGER = LoggerFactory.getLogger(TelemetrySender.class); + + private static final String PROPERTY_INSTALLATION_ID = "installationId"; + + private static final String PROPERTY_VERSION = "version"; + + private static final String PROPERTY_SERVICE_NAME = "serviceName"; + + private static final String PROJECT_INFO = "spring-data-cosmosdb/" + PropertyLoader.getProjectVersion(); + + private static final String TELEMETRY_TARGET_URL = "https://dc.services.visualstudio.com/v2/track"; + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private static final int RETRY_LIMIT = 3; // Align the retry times with sdk + + private ResponseEntity executeRequest(final TelemetryEventData eventData) { + final HttpHeaders headers = new HttpHeaders(); + + headers.add(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON.toString()); + + try { + final RestTemplate restTemplate = new RestTemplate(); + final HttpEntity body = new HttpEntity<>(MAPPER.writeValueAsString(eventData), headers); + + return restTemplate.exchange(TELEMETRY_TARGET_URL, HttpMethod.POST, body, String.class); + } catch (JsonProcessingException | HttpClientErrorException ignore) { + LOGGER.warn("Failed to exchange telemetry request, {}.", ignore.getMessage()); + } + + return null; + } + + private void sendTelemetryData(@NonNull TelemetryEventData eventData) { + ResponseEntity response = null; + + for (int i = 0; i < RETRY_LIMIT; i++) { + response = executeRequest(eventData); + + if (response != null && response.getStatusCode() == HttpStatus.OK) { + return; + } + } + + if (response != null && response.getStatusCode() != HttpStatus.OK) { + LOGGER.warn("Failed to send telemetry data, response status code {}.", response.getStatusCode().toString()); + } + } + + public void send(String name) { + Assert.hasText(name, "Event name should contain text."); + + sendTelemetryData(new TelemetryEventData(name, getProperties())); + } + + private Map getProperties() { + final Map properties = new HashMap<>(); + + properties.put(PROPERTY_VERSION, PROJECT_INFO); + properties.put(PROPERTY_SERVICE_NAME, "cosmosdb"); + properties.put(PROPERTY_INSTALLATION_ID, MacAddress.getHashMac()); + + return properties; + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java new file mode 100644 index 000000000000..67be235cbc7a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.config; + +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.sync.CosmosSyncClient; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public abstract class AbstractCosmosConfiguration extends CosmosConfigurationSupport { + + @Bean + public CosmosClient cosmosClient(CosmosDBConfig config) { + return this.cosmosDbFactory(config).getCosmosClient(); + } + + @Bean + public CosmosSyncClient cosmosSyncClient(CosmosDBConfig config) { + return this.cosmosDbFactory(config).getCosmosSyncClient(); + } + + @Qualifier(Constants.OBJECTMAPPER_BEAN_NAME) + @Autowired(required = false) + private ObjectMapper objectMapper; + + @Bean + public CosmosDbFactory cosmosDbFactory(CosmosDBConfig config) { + return new CosmosDbFactory(config); + } + + @Bean + public CosmosTemplate cosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException { + return new CosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(), + config.getDatabase()); + } + + @Bean + public ReactiveCosmosTemplate reactiveCosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException { + return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(), + config.getDatabase()); + } + + @Bean + public MappingCosmosConverter mappingCosmosConverter() throws ClassNotFoundException { + return new MappingCosmosConverter(this.cosmosMappingContext(), objectMapper); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java new file mode 100644 index 000000000000..d30c04731d0b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.config; + +import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.data.annotation.Persistent; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public abstract class CosmosConfigurationSupport { + + @Bean + public ExpressionResolver expressionResolver(BeanFactory beanFactory) { + return new ExpressionResolver(beanFactory); + } + + @Bean + public CosmosMappingContext cosmosMappingContext() throws ClassNotFoundException { + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + mappingContext.setInitialEntitySet(getInitialEntitySet()); + + return mappingContext; + } + + protected Collection getMappingBasePackages() { + final Package mappingBasePackage = getClass().getPackage(); + return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName()); + } + + protected Set> getInitialEntitySet() throws ClassNotFoundException { + final Set> initialEntitySet = new HashSet<>(); + + for (final String basePackage : getMappingBasePackages()) { + initialEntitySet.addAll(scanForEntities(basePackage)); + } + + return initialEntitySet; + } + + protected Set> scanForEntities(String basePackage) throws ClassNotFoundException { + if (!StringUtils.hasText(basePackage)) { + return Collections.emptySet(); + } + + final Set> initialEntitySet = new HashSet<>(); + + if (StringUtils.hasText(basePackage)) { + final ClassPathScanningCandidateComponentProvider componentProvider = + new ClassPathScanningCandidateComponentProvider(false); + + componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class)); + + for (final BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) { + final String className = candidate.getBeanClassName(); + Assert.notNull(className, "Bean class name is null."); + + initialEntitySet + .add(ClassUtils.forName(className, CosmosConfigurationSupport.class.getClassLoader())); + } + } + + return initialEntitySet; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java new file mode 100644 index 000000000000..f5d010a0b9fd --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java @@ -0,0 +1,220 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.config; + +import com.azure.data.cosmos.ConnectionPolicy; +import com.azure.data.cosmos.ConsistencyLevel; +import com.azure.data.cosmos.CosmosKeyCredential; +import com.azure.data.cosmos.internal.RequestOptions; +import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnosticsProcessor; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import org.springframework.util.Assert; + +import java.beans.ConstructorProperties; + +public class CosmosDBConfig { + private String uri; + + private String key; + + private String database; + + private ConnectionPolicy connectionPolicy; + + private ConsistencyLevel consistencyLevel; + + private boolean allowTelemetry; + + private RequestOptions requestOptions; + + private CosmosKeyCredential cosmosKeyCredential; + + private ResponseDiagnosticsProcessor responseDiagnosticsProcessor; + + private boolean populateQueryMetrics; + + @ConstructorProperties({"uri", "key", "database", "connectionPolicy", "consistencyLevel", "allowTelemetry", + "requestOptions", "cosmosKeyCredential", "responseDiagnosticsProcessor", + "populateQueryMetrics"}) + public CosmosDBConfig(String uri, String key, String database, ConnectionPolicy connectionPolicy, + ConsistencyLevel consistencyLevel, boolean allowTelemetry, RequestOptions requestOptions, + CosmosKeyCredential cosmosKeyCredential, + ResponseDiagnosticsProcessor responseDiagnosticsProcessor, boolean populateQueryMetrics) { + this.uri = uri; + this.key = key; + this.database = database; + this.connectionPolicy = connectionPolicy; + this.consistencyLevel = consistencyLevel; + this.allowTelemetry = allowTelemetry; + this.requestOptions = requestOptions; + this.cosmosKeyCredential = cosmosKeyCredential; + this.responseDiagnosticsProcessor = responseDiagnosticsProcessor; + this.populateQueryMetrics = populateQueryMetrics; + } + + public String getUri() { + return uri; + } + + public String getKey() { + return key; + } + + public String getDatabase() { + return database; + } + + public ConnectionPolicy getConnectionPolicy() { + return connectionPolicy; + } + + public ConsistencyLevel getConsistencyLevel() { + return consistencyLevel; + } + + public boolean isAllowTelemetry() { + return allowTelemetry; + } + + public RequestOptions getRequestOptions() { + return requestOptions; + } + + public CosmosKeyCredential getCosmosKeyCredential() { + return cosmosKeyCredential; + } + + public ResponseDiagnosticsProcessor getResponseDiagnosticsProcessor() { + return responseDiagnosticsProcessor; + } + + public boolean isPopulateQueryMetrics() { + return populateQueryMetrics; + } + + public void setResponseDiagnosticsProcessor(ResponseDiagnosticsProcessor responseDiagnosticsProcessor) { + this.responseDiagnosticsProcessor = responseDiagnosticsProcessor; + } + + public void setPopulateQueryMetrics(boolean populateQueryMetrics) { + this.populateQueryMetrics = populateQueryMetrics; + } + + public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential, + String database) { + return defaultBuilder() + .uri(uri) + .cosmosKeyCredential(cosmosKeyCredential) + .database(database) + .connectionPolicy(ConnectionPolicy.defaultPolicy()) + .consistencyLevel(ConsistencyLevel.SESSION) + .requestOptions(new RequestOptions()); + } + + public static CosmosDBConfigBuilder builder(String uri, String key, String database) { + return defaultBuilder() + .uri(uri) + .key(key) + .database(database) + .connectionPolicy(ConnectionPolicy.defaultPolicy()) + .consistencyLevel(ConsistencyLevel.SESSION) + .requestOptions(new RequestOptions()); + } + + public static CosmosDBConfigBuilder builder(String connectionString, String database) { + Assert.hasText(connectionString, "connection string should have text!"); + try { + final String uri = connectionString.split(";")[0].split("=")[1]; + final String key = connectionString.split(";")[1].split("=")[1]; + return builder(uri, key, database); + } catch (ArrayIndexOutOfBoundsException e) { + throw new CosmosDBAccessException("could not parse connection string"); + } + } + + public static CosmosDBConfigBuilder defaultBuilder() { + return new CosmosDBConfigBuilder(); + } + + public static class CosmosDBConfigBuilder { + private String uri; + private String key; + private String database; + private ConnectionPolicy connectionPolicy; + private ConsistencyLevel consistencyLevel; + private boolean allowTelemetry; + private RequestOptions requestOptions; + private CosmosKeyCredential cosmosKeyCredential; + private ResponseDiagnosticsProcessor responseDiagnosticsProcessor; + private boolean populateQueryMetrics; + + CosmosDBConfigBuilder() { + } + + public CosmosDBConfigBuilder uri(String uri) { + this.uri = uri; + return this; + } + + public CosmosDBConfigBuilder key(String key) { + this.key = key; + return this; + } + + public CosmosDBConfigBuilder database(String database) { + this.database = database; + return this; + } + + public CosmosDBConfigBuilder connectionPolicy(ConnectionPolicy connectionPolicy) { + this.connectionPolicy = connectionPolicy; + return this; + } + + public CosmosDBConfigBuilder consistencyLevel(ConsistencyLevel consistencyLevel) { + this.consistencyLevel = consistencyLevel; + return this; + } + + public CosmosDBConfigBuilder allowTelemetry(boolean allowTelemetry) { + this.allowTelemetry = allowTelemetry; + return this; + } + + public CosmosDBConfigBuilder requestOptions(RequestOptions requestOptions) { + this.requestOptions = requestOptions; + return this; + } + + public CosmosDBConfigBuilder cosmosKeyCredential(CosmosKeyCredential cosmosKeyCredential) { + this.cosmosKeyCredential = cosmosKeyCredential; + return this; + } + + public CosmosDBConfigBuilder responseDiagnosticsProcessor(ResponseDiagnosticsProcessor + responseDiagnosticsProcessor) { + this.responseDiagnosticsProcessor = responseDiagnosticsProcessor; + return this; + } + + public CosmosDBConfigBuilder populateQueryMetrics(boolean populateQueryMetrics) { + this.populateQueryMetrics = populateQueryMetrics; + return this; + } + + public CosmosDBConfig build() { + return new CosmosDBConfig(this.uri, this.key, this.database, this.connectionPolicy, this.consistencyLevel, + this.allowTelemetry, this.requestOptions, this.cosmosKeyCredential, this.responseDiagnosticsProcessor, + this.populateQueryMetrics); + } + + public String toString() { + return "CosmosDBConfig.CosmosDBConfigBuilder(uri=" + this.uri + ", key=" + this.key + + ", database=" + this.database + ", connectionPolicy=" + this.connectionPolicy + + ", consistencyLevel=" + this.consistencyLevel + ", allowTelemetry=" + this.allowTelemetry + + ", requestOptions=" + this.requestOptions + ", cosmosKeyCredential=" + this.cosmosKeyCredential + + ", responseDiagnosticsProcessor=" + this.responseDiagnosticsProcessor + ", populateQueryMetrics=" + + this.populateQueryMetrics + ")"; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java new file mode 100644 index 000000000000..907ad765b9ff --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +public interface CosmosOperations { + + /** + * Use getContainerName() instead + * @param domainType class type + * @return container name + */ + @Deprecated + String getCollectionName(Class domainType); + + String getContainerName(Class domainType); + + /** + * Use createContainerIfNotExists() instead + * @param information cosmos entity information + * @return created container properties + */ + @Deprecated + CosmosContainerProperties createCollectionIfNotExists(CosmosEntityInformation information); + + CosmosContainerProperties createContainerIfNotExists(CosmosEntityInformation information); + + List findAll(Class domainType); + + List findAll(String containerName, Class domainType); + + List findAll(PartitionKey partitionKey, Class domainType); + + T findById(Object id, Class domainType); + + T findById(String containerName, Object id, Class domainType); + + T findById(Object id, Class domainType, PartitionKey partitionKey); + + T insert(T objectToSave, PartitionKey partitionKey); + + T insert(String containerName, T objectToSave, PartitionKey partitionKey); + + void upsert(T object, PartitionKey partitionKey); + + void upsert(String containerName, T object, PartitionKey partitionKey); + + T upsertAndReturnEntity(String containerName, T object, PartitionKey partitionKey); + + void deleteById(String containerName, Object id, PartitionKey partitionKey); + + void deleteAll(String containerName, Class domainType); + + /** + * Use deleteContainer() instead + * @param containerName container name + */ + @Deprecated + void deleteCollection(String containerName); + + void deleteContainer(String containerName); + + List delete(DocumentQuery query, Class domainType, String containerName); + + List find(DocumentQuery query, Class domainType, String containerName); + + List findByIds(Iterable ids, Class domainType, String containerName); + + Boolean exists(DocumentQuery query, Class domainType, String containerName); + + Page findAll(Pageable pageable, Class domainType, String containerName); + + Page paginationQuery(DocumentQuery query, Class domainType, String containerName); + + long count(String containerName); + + long count(DocumentQuery query, Class domainType, String containerName); + + MappingCosmosConverter getConverter(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java new file mode 100644 index 000000000000..e583e987a67d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java @@ -0,0 +1,627 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.AccessCondition; +import com.azure.data.cosmos.AccessConditionType; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.CosmosContainerResponse; +import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.CosmosItemRequestOptions; +import com.azure.data.cosmos.CosmosItemResponse; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.PartitionKey; +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils; +import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator; +import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageImpl; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils.fillAndProcessResponseDiagnostics; +import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.exceptionHandler; +import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.findAPIExceptionHandler; + +public class CosmosTemplate implements CosmosOperations, ApplicationContextAware { + + private static final Logger LOGGER = LoggerFactory.getLogger(CosmosTemplate.class); + + private static final String COUNT_VALUE_KEY = "_aggregate"; + + private final MappingCosmosConverter mappingCosmosConverter; + private final String databaseName; + private final ResponseDiagnosticsProcessor responseDiagnosticsProcessor; + private final boolean isPopulateQueryMetrics; + + private final CosmosClient cosmosClient; + private Function, CosmosEntityInformation> entityInfoCreator = + Memoizer.memoize(this::getCosmosEntityInformation); + + public CosmosTemplate(CosmosDbFactory cosmosDbFactory, + MappingCosmosConverter mappingCosmosConverter, + String dbName) { + Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!"); + Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!"); + + this.mappingCosmosConverter = mappingCosmosConverter; + + this.databaseName = dbName; + this.cosmosClient = cosmosDbFactory.getCosmosClient(); + this.responseDiagnosticsProcessor = cosmosDbFactory.getConfig().getResponseDiagnosticsProcessor(); + this.isPopulateQueryMetrics = cosmosDbFactory.getConfig().isPopulateQueryMetrics(); + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + } + + public T insert(T objectToSave, PartitionKey partitionKey) { + Assert.notNull(objectToSave, "domainType should not be null"); + + return insert(getContainerName(objectToSave.getClass()), objectToSave, partitionKey); + } + + public T insert(String containerName, T objectToSave, PartitionKey partitionKey) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(objectToSave, "objectToSave should not be null"); + + final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(objectToSave); + + LOGGER.debug("execute createItem in database {} container {}", this.databaseName, containerName); + + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + options.partitionKey(partitionKey); + + @SuppressWarnings("unchecked") + final Class domainType = (Class) objectToSave.getClass(); + + final CosmosItemResponse response = cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .createItem(originalItem, options) + .doOnNext(cosmosItemResponse -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to insert item", throwable)) + .block(); + + assert response != null; + return mappingCosmosConverter.read(domainType, response.properties()); + } + + public T findById(Object id, Class domainType) { + Assert.notNull(domainType, "domainType should not be null"); + + return findById(getContainerName(domainType), id, domainType); + } + + @Override + public T findById(Object id, Class domainType, PartitionKey partitionKey) { + Assert.notNull(domainType, "domainType should not be null"); + Assert.notNull(partitionKey, "partitionKey should not be null"); + assertValidId(id); + + final String containerName = getContainerName(domainType); + return cosmosClient + .getDatabase(databaseName) + .getContainer(containerName) + .getItem(id.toString(), partitionKey) + .read() + .flatMap(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return Mono.justOrEmpty(toDomainObject(domainType, + cosmosItemResponse.properties())); + }) + .onErrorResume(throwable -> + findAPIExceptionHandler("Failed to find item", throwable)) + .block(); + } + + public T findById(String containerName, Object id, Class domainType) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(domainType, "domainType should not be null"); + assertValidId(id); + + final String query = String.format("select * from root where root.id = '%s'", id.toString()); + final FeedOptions options = new FeedOptions(); + options.enableCrossPartitionQuery(true); + options.populateQueryMetrics(isPopulateQueryMetrics); + return cosmosClient + .getDatabase(databaseName) + .getContainer(containerName) + .queryItems(query, options) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Mono.justOrEmpty(cosmosItemFeedResponse + .results() + .stream() + .map(cosmosItem -> mappingCosmosConverter.read(domainType, cosmosItem)) + .findFirst()); + }) + .onErrorResume(throwable -> + findAPIExceptionHandler("Failed to find item", throwable)) + .blockFirst(); + } + + public void upsert(T object, PartitionKey partitionKey) { + Assert.notNull(object, "Upsert object should not be null"); + + upsert(getContainerName(object.getClass()), object, partitionKey); + } + + public void upsert(String containerName, T object, PartitionKey partitionKey) { + upsertAndReturnEntity(containerName, object, partitionKey); + } + + public T upsertAndReturnEntity(String containerName, T object, PartitionKey partitionKey) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(object, "Upsert object should not be null"); + + final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(object); + + LOGGER.debug("execute upsert item in database {} container {}", this.databaseName, containerName); + + @SuppressWarnings("unchecked") + final Class domainType = (Class) object.getClass(); + + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + options.partitionKey(partitionKey); + applyVersioning(domainType, originalItem, options); + + final CosmosItemResponse cosmosItemResponse = cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .upsertItem(originalItem, options) + .doOnNext(response -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + response, null)) + .onErrorResume(throwable -> exceptionHandler("Failed to upsert item", throwable)) + .block(); + + assert cosmosItemResponse != null; + return mappingCosmosConverter.read(domainType, cosmosItemResponse.properties()); + } + + public List findAll(Class domainType) { + Assert.notNull(domainType, "domainType should not be null"); + + return findAll(getContainerName(domainType), domainType); + } + + public List findAll(String containerName, final Class domainType) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(domainType, "domainType should not be null"); + + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)); + + final List items = findItems(query, domainType, containerName); + return items.stream() + .map(d -> getConverter().read(domainType, d)) + .collect(Collectors.toList()); + } + + @Override + public List findAll(PartitionKey partitionKey, final Class domainType) { + Assert.notNull(partitionKey, "partitionKey should not be null"); + Assert.notNull(domainType, "domainType should not be null"); + + final String containerName = getContainerName(domainType); + + final FeedOptions feedOptions = new FeedOptions(); + feedOptions.partitionKey(partitionKey); + feedOptions.populateQueryMetrics(isPopulateQueryMetrics); + + return cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .readAllItems(feedOptions) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Flux.fromIterable(cosmosItemFeedResponse.results()); + }) + .map(cosmosItemProperties -> toDomainObject(domainType, cosmosItemProperties)) + .onErrorResume(throwable -> + exceptionHandler("Failed to find items", throwable)) + .collectList() + .block(); + } + + public void deleteAll(@NonNull String containerName, @NonNull Class domainType) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)); + + this.delete(query, domainType, containerName); + } + + @Override + public void deleteCollection(@NonNull String containerName) { + deleteContainer(containerName); + } + + @Override + public void deleteContainer(@NonNull String containerName) { + Assert.hasText(containerName, "containerName should have text."); + cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .delete() + .doOnNext(response -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + response, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete container", throwable)) + .block(); + } + + public String getCollectionName(Class domainType) { + return getContainerName(domainType); + } + + @Override + public String getContainerName(Class domainType) { + Assert.notNull(domainType, "domainType should not be null"); + + return entityInfoCreator.apply(domainType).getContainerName(); + } + + @Override + public CosmosContainerProperties createCollectionIfNotExists(@NonNull CosmosEntityInformation information) { + return createContainerIfNotExists(information); + } + + @Override + public CosmosContainerProperties createContainerIfNotExists(CosmosEntityInformation information) { + final CosmosContainerResponse response = cosmosClient + .createDatabaseIfNotExists(this.databaseName) + .onErrorResume(throwable -> + exceptionHandler("Failed to create database", throwable)) + .flatMap(cosmosDatabaseResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosDatabaseResponse, null); + final CosmosContainerProperties cosmosContainerProperties = new CosmosContainerProperties( + information.getContainerName(), + "/" + information.getPartitionKeyFieldName()); + cosmosContainerProperties.defaultTimeToLive(information.getTimeToLive()); + cosmosContainerProperties.indexingPolicy(information.getIndexingPolicy()); + return cosmosDatabaseResponse + .database() + .createContainerIfNotExists(cosmosContainerProperties, information.getRequestUnit()) + .onErrorResume(throwable -> + exceptionHandler("Failed to create container", throwable)) + .doOnNext(cosmosContainerResponse -> + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosContainerResponse, null)); + }) + .block(); + assert response != null; + return response.properties(); + } + + public void deleteById(String containerName, Object id, PartitionKey partitionKey) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + assertValidId(id); + + LOGGER.debug("execute deleteById in database {} container {}", this.databaseName, containerName); + + if (partitionKey == null) { + partitionKey = PartitionKey.None; + } + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + options.partitionKey(partitionKey); + cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .getItem(id.toString(), partitionKey) + .delete(options) + .doOnNext(response -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + response, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete item", throwable)) + .block(); + } + + @Override + public List findByIds(Iterable ids, Class domainType, String containerName) { + Assert.notNull(ids, "Id list should not be null"); + Assert.notNull(domainType, "domainType should not be null."); + Assert.hasText(containerName, "container should not be null, empty or only whitespaces"); + + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.IN, "id", + Collections.singletonList(ids))); + return find(query, domainType, containerName); + } + + public List find(@NonNull DocumentQuery query, @NonNull Class domainType, String containerName) { + Assert.notNull(query, "DocumentQuery should not be null."); + Assert.notNull(domainType, "domainType should not be null."); + Assert.hasText(containerName, "container should not be null, empty or only whitespaces"); + + return findItems(query, domainType, containerName) + .stream() + .map(cosmosItemProperties -> toDomainObject(domainType, cosmosItemProperties)) + .collect(Collectors.toList()); + } + + public Boolean exists(@NonNull DocumentQuery query, @NonNull Class domainType, String containerName) { + return this.find(query, domainType, containerName).size() > 0; + } + + /** + * Delete the DocumentQuery, need to query the domains at first, then delete the item + * from the result. + * The cosmosdb Sql API do _NOT_ support DELETE query, we cannot add one DeleteQueryGenerator. + * + * @param query The representation for query method. + * @param domainType Class of domain + * @param containerName Container name of database + * @param + * @return All the deleted items as List. + */ + @Override + public List delete(@NonNull DocumentQuery query, @NonNull Class domainType, + @NonNull String containerName) { + Assert.notNull(query, "DocumentQuery should not be null."); + Assert.notNull(domainType, "domainType should not be null."); + Assert.hasText(containerName, "container should not be null, empty or only whitespaces"); + + final List results = findItems(query, domainType, containerName); + final List partitionKeyName = getPartitionKeyNames(domainType); + + return results.stream().map(cosmosItemProperties -> { + final CosmosItemResponse cosmosItemResponse = deleteItem(cosmosItemProperties, + partitionKeyName, containerName, domainType); + return getConverter().read(domainType, cosmosItemResponse.properties()); + }).collect(Collectors.toList()); + } + + @Override + public Page findAll(Pageable pageable, Class domainType, String containerName) { + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(pageable); + if (pageable.getSort().isSorted()) { + query.with(pageable.getSort()); + } + + return paginationQuery(query, domainType, containerName); + } + + @Override + public Page paginationQuery(DocumentQuery query, Class domainType, String containerName) { + Assert.isTrue(query.getPageable().getPageSize() > 0, "pageable should have page size larger than 0"); + Assert.hasText(containerName, "container should not be null, empty or only whitespaces"); + + final Pageable pageable = query.getPageable(); + final FeedOptions feedOptions = new FeedOptions(); + if (pageable instanceof CosmosPageRequest) { + feedOptions.requestContinuation(((CosmosPageRequest) pageable).getRequestContinuation()); + } + + feedOptions.maxItemCount(pageable.getPageSize()); + feedOptions.enableCrossPartitionQuery(query.isCrossPartitionQuery(getPartitionKeyNames(domainType))); + feedOptions.populateQueryMetrics(isPopulateQueryMetrics); + + final SqlQuerySpec sqlQuerySpec = new FindQuerySpecGenerator().generateCosmos(query); + final FeedResponse feedResponse = cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, feedOptions) + .doOnNext(propertiesFeedResponse -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, propertiesFeedResponse)) + .onErrorResume(throwable -> + exceptionHandler("Failed to query items", throwable)) + .next() + .block(); + + assert feedResponse != null; + final Iterator it = feedResponse.results().iterator(); + + final List result = new ArrayList<>(); + for (int index = 0; it.hasNext() && index < pageable.getPageSize(); index++) { + + final CosmosItemProperties cosmosItemProperties = it.next(); + if (cosmosItemProperties == null) { + continue; + } + + final T entity = mappingCosmosConverter.read(domainType, cosmosItemProperties); + result.add(entity); + } + + final long total = count(query, domainType, containerName); + final int contentSize = result.size(); + + int pageSize; + + if (contentSize < pageable.getPageSize() && contentSize > 0) { + // If the content size is less than page size, + // this means, cosmosDB is returning less items than page size, + // because of either RU limit, or payload limit + + // Set the page size to content size. + pageSize = contentSize; + } else { + pageSize = pageable.getPageSize(); + } + + final CosmosPageRequest pageRequest = CosmosPageRequest.of(pageable.getOffset(), + pageable.getPageNumber(), + pageSize, + feedResponse.continuationToken(), + query.getSort()); + + return new CosmosPageImpl<>(result, pageRequest, total); + } + + @Override + public long count(String containerName) { + Assert.hasText(containerName, "container name should not be empty"); + + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)); + final Long count = getCountValue(query, true, containerName); + assert count != null; + return count; + } + + @Override + public long count(DocumentQuery query, Class domainType, String containerName) { + Assert.notNull(domainType, "domainType should not be null"); + Assert.hasText(containerName, "container name should not be empty"); + + final boolean isCrossPartitionQuery = + query.isCrossPartitionQuery(getPartitionKeyNames(domainType)); + final Long count = getCountValue(query, isCrossPartitionQuery, containerName); + assert count != null; + return count; + } + + @Override + public MappingCosmosConverter getConverter() { + return this.mappingCosmosConverter; + } + + private Long getCountValue(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) { + final SqlQuerySpec querySpec = new CountQueryGenerator().generateCosmos(query); + final FeedOptions options = new FeedOptions(); + + options.enableCrossPartitionQuery(isCrossPartitionQuery); + options.populateQueryMetrics(isPopulateQueryMetrics); + + return executeQuery(querySpec, containerName, options) + .onErrorResume(throwable -> + exceptionHandler("Failed to get count value", throwable)) + .doOnNext(response -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, response)) + .next() + .map(r -> r.results().get(0).getLong(COUNT_VALUE_KEY)) + .block(); + } + + private Flux> executeQuery(SqlQuerySpec sqlQuerySpec, String containerName, + FeedOptions options) { + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, options) + .onErrorResume(throwable -> + exceptionHandler("Failed to execute query", throwable)); + } + + private List getPartitionKeyNames(Class domainType) { + final CosmosEntityInformation entityInfo = entityInfoCreator.apply(domainType); + + if (entityInfo.getPartitionKeyFieldName() == null) { + return new ArrayList<>(); + } + + return Collections.singletonList(entityInfo.getPartitionKeyFieldName()); + } + + private void assertValidId(Object id) { + Assert.notNull(id, "id should not be null"); + if (id instanceof String) { + Assert.hasText(id.toString(), "id should not be empty or only whitespaces."); + } + } + + private List findItems(@NonNull DocumentQuery query, + @NonNull Class domainType, + @NonNull String containerName) { + final SqlQuerySpec sqlQuerySpec = new FindQuerySpecGenerator().generateCosmos(query); + final boolean isCrossPartitionQuery = + query.isCrossPartitionQuery(getPartitionKeyNames(domainType)); + final FeedOptions feedOptions = new FeedOptions(); + feedOptions.enableCrossPartitionQuery(isCrossPartitionQuery); + feedOptions.populateQueryMetrics(isPopulateQueryMetrics); + + return cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, feedOptions) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Flux.fromIterable(cosmosItemFeedResponse.results()); + }) + .onErrorResume(throwable -> + exceptionHandler("Failed to find items", throwable)) + .collectList() + .block(); + } + + private CosmosItemResponse deleteItem(@NonNull CosmosItemProperties cosmosItemProperties, + @NonNull List partitionKeyNames, + String containerName, + @NonNull Class domainType) { + Assert.isTrue(partitionKeyNames.size() <= 1, "Only one Partition is supported."); + + PartitionKey partitionKey = null; + + if (!partitionKeyNames.isEmpty() && StringUtils.hasText(partitionKeyNames.get(0))) { + partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0))); + } + + if (partitionKey == null) { + partitionKey = PartitionKey.None; + } + + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(partitionKey); + applyVersioning(domainType, cosmosItemProperties, options); + + return cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .getItem(cosmosItemProperties.id(), partitionKey) + .delete(options) + .doOnNext(response -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + response, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete item", throwable)) + .block(); + } + + private T toDomainObject(@NonNull Class domainType, CosmosItemProperties cosmosItemProperties) { + return mappingCosmosConverter.read(domainType, cosmosItemProperties); + } + + private void applyVersioning(Class domainType, + CosmosItemProperties cosmosItemProperties, + CosmosItemRequestOptions options) { + + if (entityInfoCreator.apply(domainType).isVersioned()) { + final AccessCondition accessCondition = new AccessCondition(); + accessCondition.type(AccessConditionType.IF_MATCH); + accessCondition.condition(cosmosItemProperties.etag()); + options.accessCondition(accessCondition); + } + } + + private CosmosEntityInformation getCosmosEntityInformation(Class domainType) { + return new CosmosEntityInformation<>(domainType); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java new file mode 100644 index 000000000000..152ef6a60800 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.CosmosContainerResponse; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface ReactiveCosmosOperations { + + String getContainerName(Class domainType); + + /** + * Use createContainerIfNotExists() instead + * @param information cosmos entity information + * @return Mono of cosmos container response + */ + @Deprecated + Mono createCollectionIfNotExists(CosmosEntityInformation information); + + Mono createContainerIfNotExists(CosmosEntityInformation information); + + Flux findAll(String containerName, Class domainType); + + Flux findAll(Class domainType); + + Flux findAll(PartitionKey partitionKey, Class domainType); + + Mono findById(Object id, Class domainType); + + Mono findById(String containerName, Object id, Class domainType); + + Mono findById(Object id, Class domainType, PartitionKey partitionKey); + + Mono insert(T objectToSave, PartitionKey partitionKey); + + Mono insert(String containerName, Object objectToSave, PartitionKey partitionKey); + + Mono upsert(T object, PartitionKey partitionKey); + + Mono upsert(String containerName, T object, PartitionKey partitionKey); + + Mono deleteById(String containerName, Object id, PartitionKey partitionKey); + + Mono deleteAll(String containerName, String partitionKey); + + void deleteContainer(String containerName); + + Flux delete(DocumentQuery query, Class domainType, String containerName); + + Flux find(DocumentQuery query, Class domainType, String containerName); + + Mono exists(DocumentQuery query, Class domainType, String containerName); + + Mono existsById(Object id, Class domainType, String containerName); + + Mono count(String containerName); + + Mono count(DocumentQuery query, String containerName); + + MappingCosmosConverter getConverter(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java new file mode 100644 index 000000000000..6db018dabf7a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java @@ -0,0 +1,680 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.AccessCondition; +import com.azure.data.cosmos.AccessConditionType; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.CosmosContainerResponse; +import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.CosmosItemRequestOptions; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.PartitionKey; +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils; +import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator; +import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import static com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils.fillAndProcessResponseDiagnostics; +import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.exceptionHandler; +import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.findAPIExceptionHandler; + +public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, ApplicationContextAware { + private static final String COUNT_VALUE_KEY = "_aggregate"; + + private final MappingCosmosConverter mappingCosmosConverter; + private final String databaseName; + + private final CosmosClient cosmosClient; + private final ResponseDiagnosticsProcessor responseDiagnosticsProcessor; + private final boolean isPopulateQueryMetrics; + + private Function, CosmosEntityInformation> entityInfoCreator = + Memoizer.memoize(this::getCosmosEntityInformation); + + private final List containerNameCache; + + /** + * Constructor + * + * @param cosmosDbFactory the cosmosdbfactory + * @param mappingCosmosConverter the mappingCosmosConverter + * @param dbName database name + */ + public ReactiveCosmosTemplate(CosmosDbFactory cosmosDbFactory, + MappingCosmosConverter mappingCosmosConverter, + String dbName) { + Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!"); + Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!"); + + this.mappingCosmosConverter = mappingCosmosConverter; + this.databaseName = dbName; + this.containerNameCache = new ArrayList<>(); + + this.cosmosClient = cosmosDbFactory.getCosmosClient(); + this.responseDiagnosticsProcessor = cosmosDbFactory.getConfig().getResponseDiagnosticsProcessor(); + this.isPopulateQueryMetrics = cosmosDbFactory.getConfig().isPopulateQueryMetrics(); + } + + /** + * @param applicationContext the application context + * @throws BeansException the bean exception + */ + public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { + // NOTE: When application context instance variable gets introduced, assign it here. + } + + /** + * Creates a container if it doesn't already exist + * + * @param information the CosmosEntityInformation + * @return Mono containing CosmosContainerResponse + */ + @Override + public Mono createCollectionIfNotExists(CosmosEntityInformation information) { + return createContainerIfNotExists(information); + } + + /** + * Creates a container if it doesn't already exist + * + * @param information the CosmosEntityInformation + * @return Mono containing CosmosContainerResponse + */ + @Override + public Mono createContainerIfNotExists(CosmosEntityInformation information) { + + return cosmosClient + .createDatabaseIfNotExists(this.databaseName) + .onErrorResume(throwable -> + exceptionHandler("Failed to create database", throwable)) + .flatMap(cosmosDatabaseResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosDatabaseResponse, null); + final CosmosContainerProperties cosmosContainerProperties = new CosmosContainerProperties( + information.getContainerName(), + "/" + information.getPartitionKeyFieldName()); + cosmosContainerProperties.defaultTimeToLive(information.getTimeToLive()); + cosmosContainerProperties.indexingPolicy(information.getIndexingPolicy()); + return cosmosDatabaseResponse + .database() + .createContainerIfNotExists(cosmosContainerProperties, information.getRequestUnit()) + .map(cosmosContainerResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosContainerResponse, null); + this.containerNameCache.add(information.getContainerName()); + return cosmosContainerResponse; + }) + .onErrorResume(throwable -> + exceptionHandler("Failed to create container", throwable)); + }); + + } + + /** + * Find all items in a given container + * + * @param containerName the containerName + * @param domainType the domainType + * @return Flux with all the found items or error + */ + @Override + public Flux findAll(String containerName, Class domainType) { + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)); + + return find(query, domainType, containerName); + } + + /** + * Find all items in a given container + * + * @param domainType the domainType + * @return Flux with all the found items or error + */ + @Override + public Flux findAll(Class domainType) { + return findAll(domainType.getSimpleName(), domainType); + } + + @Override + public Flux findAll(PartitionKey partitionKey, Class domainType) { + Assert.notNull(partitionKey, "partitionKey should not be null"); + Assert.notNull(domainType, "domainType should not be null"); + + final String containerName = getContainerName(domainType); + + final FeedOptions feedOptions = new FeedOptions(); + feedOptions.partitionKey(partitionKey); + feedOptions.populateQueryMetrics(isPopulateQueryMetrics); + + return cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .readAllItems(feedOptions) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Flux.fromIterable(cosmosItemFeedResponse.results()); + }) + .map(cosmosItemProperties -> toDomainObject(domainType, cosmosItemProperties)) + .onErrorResume(throwable -> + exceptionHandler("Failed to find items", throwable)); + } + + /** + * Find by id + * + * @param id the id + * @param domainType the domainType + * @return Mono with the item or error + */ + @Override + public Mono findById(Object id, Class domainType) { + Assert.notNull(domainType, "domainType should not be null"); + return findById(getContainerName(domainType), id, domainType); + } + + /** + * Find by id + * + * @param containerName the containername + * @param id the id + * @param domainType the entity class + * @return Mono with the item or error + */ + @Override + public Mono findById(String containerName, Object id, Class domainType) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(domainType, "domainType should not be null"); + assertValidId(id); + + final String query = String.format("select * from root where root.id = '%s'", id.toString()); + final FeedOptions options = new FeedOptions(); + options.enableCrossPartitionQuery(true); + options.populateQueryMetrics(isPopulateQueryMetrics); + + return cosmosClient.getDatabase(databaseName) + .getContainer(containerName) + .queryItems(query, options) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Mono.justOrEmpty(cosmosItemFeedResponse + .results() + .stream() + .map(cosmosItem -> toDomainObject(domainType, cosmosItem)) + .findFirst()); + }) + .onErrorResume(throwable -> + findAPIExceptionHandler("Failed to find item", throwable)) + .next(); + } + + /** + * Find by id + * + * @param id the id + * @param domainType the entity class + * @param partitionKey partition Key + * @return Mono with the item or error + */ + @Override + public Mono findById(Object id, Class domainType, PartitionKey partitionKey) { + Assert.notNull(domainType, "domainType should not be null"); + assertValidId(id); + + final String containerName = getContainerName(domainType); + return cosmosClient.getDatabase(databaseName) + .getContainer(containerName) + .getItem(id.toString(), partitionKey) + .read() + .flatMap(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return Mono.justOrEmpty(toDomainObject(domainType, + cosmosItemResponse.properties())); + }) + .onErrorResume(throwable -> + findAPIExceptionHandler("Failed to find item", throwable)); + } + + /** + * Insert + * + * @param objectToSave the object to save + * @param partitionKey the partition key + * @return Mono with the item or error + */ + public Mono insert(T objectToSave, PartitionKey partitionKey) { + Assert.notNull(objectToSave, "domainType should not be null"); + + return insert(getContainerName(objectToSave.getClass()), objectToSave, partitionKey); + } + + /** + * Insert + * + * @param objectToSave the object to save + * @return Mono with the item or error + */ + public Mono insert(T objectToSave) { + Assert.notNull(objectToSave, "objectToSave should not be null"); + + final Class domainType = (Class) objectToSave.getClass(); + final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(objectToSave); + return cosmosClient.getDatabase(this.databaseName) + .getContainer(getContainerName(objectToSave.getClass())) + .createItem(originalItem, new CosmosItemRequestOptions()) + .onErrorResume(throwable -> + exceptionHandler("Failed to insert item", throwable)) + .flatMap(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return Mono.just(toDomainObject(domainType, cosmosItemResponse.properties())); + }); + } + + /** + * Insert + * + * @param containerName the container name + * @param objectToSave the object to save + * @param partitionKey the partition key + * @return Mono with the item or error + */ + public Mono insert(String containerName, Object objectToSave, PartitionKey partitionKey) { + Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); + Assert.notNull(objectToSave, "objectToSave should not be null"); + + final Class domainType = (Class) objectToSave.getClass(); + final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(objectToSave); + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + if (partitionKey != null) { + options.partitionKey(partitionKey); + } + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .createItem(originalItem, options) + .onErrorResume(throwable -> + exceptionHandler("Failed to insert item", throwable)) + .flatMap(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return Mono.just(toDomainObject(domainType, cosmosItemResponse.properties())); + }); + } + + /** + * Upsert + * + * @param object the object to upsert + * @param partitionKey the partition key + * @return Mono with the item or error + */ + @Override + public Mono upsert(T object, PartitionKey partitionKey) { + return upsert(getContainerName(object.getClass()), object, partitionKey); + } + + /** + * Upsert + * + * @param containerName the container name + * @param object the object to save + * @param partitionKey the partition key + * @return Mono with the item or error + */ + @Override + public Mono upsert(String containerName, T object, PartitionKey partitionKey) { + final Class domainType = (Class) object.getClass(); + final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(object); + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + if (partitionKey != null) { + options.partitionKey(partitionKey); + } + + applyVersioning(object.getClass(), originalItem, options); + + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .upsertItem(originalItem, options) + .flatMap(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return Mono.just(toDomainObject(domainType, cosmosItemResponse.properties())); + }) + .onErrorResume(throwable -> + exceptionHandler("Failed to upsert item", throwable)); + } + + /** + * Delete an item by id + * + * @param containerName the container name + * @param id the id + * @param partitionKey the partition key + * @return void Mono + */ + @Override + public Mono deleteById(String containerName, Object id, PartitionKey partitionKey) { + Assert.hasText(containerName, "container name should not be null, empty or only whitespaces"); + assertValidId(id); + + if (partitionKey == null) { + partitionKey = PartitionKey.None; + } + + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(); + options.partitionKey(partitionKey); + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .getItem(id.toString(), partitionKey) + .delete(options) + .doOnNext(cosmosItemResponse -> + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete item", throwable)) + .then(); + } + + /** + * Delete all items in a container + * + * @param containerName the container name + * @param partitionKeyName the partition key path + * @return void Mono + */ + @Override + public Mono deleteAll(String containerName, String partitionKeyName) { + Assert.hasText(containerName, "container name should not be null, empty or only whitespaces"); + Assert.notNull(partitionKeyName, "partitionKeyName should not be null"); + + final Criteria criteria = Criteria.getInstance(CriteriaType.ALL); + final DocumentQuery query = new DocumentQuery(criteria); + final SqlQuerySpec sqlQuerySpec = new FindQuerySpecGenerator().generateCosmos(query); + final FeedOptions options = new FeedOptions(); + final boolean isCrossPartitionQuery = query.isCrossPartitionQuery(Collections.singletonList(partitionKeyName)); + options.enableCrossPartitionQuery(isCrossPartitionQuery); + options.populateQueryMetrics(isPopulateQueryMetrics); + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, options) + .onErrorResume(throwable -> + exceptionHandler("Failed to query items", throwable)) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Flux.fromIterable(cosmosItemFeedResponse.results()); + }) + .flatMap(cosmosItemProperties -> cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .getItem(cosmosItemProperties.id(), cosmosItemProperties.get(partitionKeyName)) + .delete() + .doOnNext(cosmosItemResponse -> + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete items", throwable))) + .then(); + } + + /** + * Delete items matching query + * + * @param query the document query + * @param domainType the entity class + * @param containerName the container name + * @return Mono + */ + @Override + public Flux delete(DocumentQuery query, Class domainType, String containerName) { + Assert.notNull(query, "DocumentQuery should not be null."); + Assert.notNull(domainType, "domainType should not be null."); + Assert.hasText(containerName, "container name should not be null, empty or only whitespaces"); + + final Flux results = findItems(query, domainType, containerName); + final List partitionKeyName = getPartitionKeyNames(domainType); + + return results.flatMap(d -> deleteItem(d, partitionKeyName, containerName, domainType)) + .flatMap(cosmosItemProperties -> Mono.just(toDomainObject(domainType, cosmosItemProperties))); + } + + /** + * Find items + * + * @param query the document query + * @param domainType the entity class + * @param containerName the container name + * @return Flux with found items or error + */ + @Override + public Flux find(DocumentQuery query, Class domainType, String containerName) { + return findItems(query, domainType, containerName) + .map(cosmosItemProperties -> toDomainObject(domainType, cosmosItemProperties)); + } + + /** + * Exists + * + * @param query the document query + * @param domainType the entity class + * @param containerName the container name + * @return Mono with a boolean or error + */ + @Override + public Mono exists(DocumentQuery query, Class domainType, String containerName) { + return count(query, true, containerName).flatMap(count -> Mono.just(count > 0)); + } + + /** + * Exists + * @param id the id + * @param domainType the entity class + * @param containerName the containercontainer nam,e + * @return Mono with a boolean or error + */ + public Mono existsById(Object id, Class domainType, String containerName) { + return findById(containerName, id, domainType) + .flatMap(o -> Mono.just(o != null)); + } + + /** + * Count + * + * @param containerName the container name + * @return Mono with the count or error + */ + @Override + public Mono count(String containerName) { + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)); + return count(query, true, containerName); + } + + /** + * Count + * + * @param query the document query + * @param containerName the container name + * @return Mono with count or error + */ + @Override + public Mono count(DocumentQuery query, String containerName) { + return count(query, true, containerName); + } + + @Override + public MappingCosmosConverter getConverter() { + return mappingCosmosConverter; + } + + public Mono count(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) { + return getCountValue(query, isCrossPartitionQuery, containerName); + } + + private Mono getCountValue(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) { + final SqlQuerySpec querySpec = new CountQueryGenerator().generateCosmos(query); + final FeedOptions options = new FeedOptions(); + + options.enableCrossPartitionQuery(isCrossPartitionQuery); + options.populateQueryMetrics(isPopulateQueryMetrics); + + return executeQuery(querySpec, containerName, options) + .doOnNext(feedResponse -> fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, feedResponse)) + .onErrorResume(throwable -> + exceptionHandler("Failed to get count value", throwable)) + .next() + .map(r -> r.results().get(0).getLong(COUNT_VALUE_KEY)); + } + + private Flux> executeQuery(SqlQuerySpec sqlQuerySpec, String containerName, + FeedOptions options) { + + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, options) + .onErrorResume(throwable -> + exceptionHandler("Failed to execute query", throwable)); + } + + /** + * Delete container with container name + * + * @param containerName the container name + */ + @Override + public void deleteContainer(@NonNull String containerName) { + Assert.hasText(containerName, "containerName should have text."); + cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .delete() + .doOnNext(cosmosContainerResponse -> + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosContainerResponse, null)) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete container", throwable)) + .block(); + this.containerNameCache.remove(containerName); + } + + /** + * @param domainType the domain class + * @return the container name + */ + public String getContainerName(Class domainType) { + Assert.notNull(domainType, "domainType should not be null"); + + return entityInfoCreator.apply(domainType).getContainerName(); + } + + private Flux findItems(@NonNull DocumentQuery query, @NonNull Class domainType, + @NonNull String containerName) { + final SqlQuerySpec sqlQuerySpec = new FindQuerySpecGenerator().generateCosmos(query); + final boolean isCrossPartitionQuery = query.isCrossPartitionQuery(getPartitionKeyNames(domainType)); + final FeedOptions feedOptions = new FeedOptions(); + feedOptions.enableCrossPartitionQuery(isCrossPartitionQuery); + feedOptions.populateQueryMetrics(isPopulateQueryMetrics); + + return cosmosClient + .getDatabase(this.databaseName) + .getContainer(containerName) + .queryItems(sqlQuerySpec, feedOptions) + .flatMap(cosmosItemFeedResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Flux.fromIterable(cosmosItemFeedResponse.results()); + }) + .onErrorResume(throwable -> + exceptionHandler("Failed to query items", throwable)); + } + + private void assertValidId(Object id) { + Assert.notNull(id, "id should not be null"); + if (id instanceof String) { + Assert.hasText(id.toString(), "id should not be empty or only whitespaces."); + } + } + + private List getPartitionKeyNames(Class domainType) { + final CosmosEntityInformation entityInfo = entityInfoCreator.apply(domainType); + + if (entityInfo.getPartitionKeyFieldName() == null) { + return new ArrayList<>(); + } + + return Collections.singletonList(entityInfo.getPartitionKeyFieldName()); + } + + private Mono deleteItem(@NonNull CosmosItemProperties cosmosItemProperties, + @NonNull List partitionKeyNames, + String containerName, + @NonNull Class domainType) { + Assert.isTrue(partitionKeyNames.size() <= 1, "Only one Partition is supported."); + + PartitionKey partitionKey = null; + + if (!partitionKeyNames.isEmpty() && StringUtils.hasText(partitionKeyNames.get(0))) { + partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0))); + } + + final CosmosItemRequestOptions options = new CosmosItemRequestOptions(partitionKey); + applyVersioning(domainType, cosmosItemProperties, options); + + return cosmosClient.getDatabase(this.databaseName) + .getContainer(containerName) + .getItem(cosmosItemProperties.id(), partitionKey) + .delete(options) + .map(cosmosItemResponse -> { + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + cosmosItemResponse, null); + return cosmosItemProperties; + }) + .onErrorResume(throwable -> + exceptionHandler("Failed to delete item", throwable)); + } + + private T toDomainObject(@NonNull Class domainType, CosmosItemProperties cosmosItemProperties) { + return mappingCosmosConverter.read(domainType, cosmosItemProperties); + } + + private void applyVersioning(Class domainType, + CosmosItemProperties cosmosItemProperties, + CosmosItemRequestOptions options) { + + if (entityInfoCreator.apply(domainType).isVersioned()) { + final AccessCondition accessCondition = new AccessCondition(); + accessCondition.type(AccessConditionType.IF_MATCH); + accessCondition.condition(cosmosItemProperties.etag()); + options.accessCondition(accessCondition); + } + } + + private CosmosEntityInformation getCosmosEntityInformation(Class domainType) { + return new CosmosEntityInformation<>(domainType); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java new file mode 100644 index 000000000000..6745e055809a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.CosmosResponseDiagnostics; +import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.FeedResponseDiagnostics; +import com.azure.data.cosmos.Resource; + +public class ResponseDiagnostics { + + private CosmosResponseDiagnostics cosmosResponseDiagnostics; + private FeedResponseDiagnostics feedResponseDiagnostics; + private CosmosResponseStatistics cosmosResponseStatistics; + + public ResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics, + FeedResponseDiagnostics feedResponseDiagnostics) { + this.cosmosResponseDiagnostics = cosmosResponseDiagnostics; + this.feedResponseDiagnostics = feedResponseDiagnostics; + } + + public ResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics, + FeedResponseDiagnostics feedResponseDiagnostics, + CosmosResponseStatistics cosmosResponseStatistics) { + this.cosmosResponseDiagnostics = cosmosResponseDiagnostics; + this.feedResponseDiagnostics = feedResponseDiagnostics; + this.cosmosResponseStatistics = cosmosResponseStatistics; + } + + public CosmosResponseDiagnostics getCosmosResponseDiagnostics() { + return cosmosResponseDiagnostics; + } + + public void setCosmosResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics) { + this.cosmosResponseDiagnostics = cosmosResponseDiagnostics; + } + + public FeedResponseDiagnostics getFeedResponseDiagnostics() { + return feedResponseDiagnostics; + } + + public void setFeedResponseDiagnostics(FeedResponseDiagnostics feedResponseDiagnostics) { + this.feedResponseDiagnostics = feedResponseDiagnostics; + } + + public CosmosResponseStatistics getCosmosResponseStatistics() { + return cosmosResponseStatistics; + } + + public void setCosmosResponseStatistics(CosmosResponseStatistics cosmosResponseStatistics) { + this.cosmosResponseStatistics = cosmosResponseStatistics; + } + + @Override + public String toString() { + final StringBuilder diagnostics = new StringBuilder(); + if (cosmosResponseDiagnostics != null) { + diagnostics.append("cosmosResponseDiagnostics={") + .append(cosmosResponseDiagnostics) + .append("}"); + } + if (feedResponseDiagnostics != null) { + if (diagnostics.length() != 0) { + diagnostics.append(", "); + } + diagnostics.append("feedResponseDiagnostics={") + .append(feedResponseDiagnostics) + .append("}"); + } + if (cosmosResponseStatistics != null) { + if (diagnostics.length() != 0) { + diagnostics.append(", "); + } + diagnostics.append("cosmosResponseStatistics={") + .append(cosmosResponseStatistics) + .append("}"); + } + return diagnostics.toString(); + } + + public static class CosmosResponseStatistics { + + private final double requestCharge; + private final String activityId; + + public CosmosResponseStatistics(FeedResponse feedResponse) { + this.requestCharge = feedResponse.requestCharge(); + this.activityId = feedResponse.activityId(); + } + + public double getRequestCharge() { + return requestCharge; + } + + public String getActivityId() { + return activityId; + } + + @Override + public String toString() { + return "CosmosResponseStatistics{" + + "requestCharge=" + requestCharge + + ", activityId='" + activityId + '\'' + + '}'; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java new file mode 100644 index 000000000000..3e1542c6b328 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import javax.annotation.Nullable; + +public interface ResponseDiagnosticsProcessor { + + /** + * Gets called after receiving response from CosmosDb. + * Response Diagnostics are collected from API responses and + * then set in {@link ResponseDiagnostics} object. + *

+ * In case of missing diagnostics from CosmosDb, responseDiagnostics will be null. + * + * @param responseDiagnostics responseDiagnostics object containing CosmosDb response + * diagnostics information + */ + void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java new file mode 100644 index 000000000000..4caafc2cc3ef --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java @@ -0,0 +1,176 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.convert; + +import com.azure.data.cosmos.CosmosItemProperties; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentEntity; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.data.convert.EntityConverter; +import org.springframework.data.mapping.MappingException; +import org.springframework.data.mapping.PersistentPropertyAccessor; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.ConvertingPropertyAccessor; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +import static com.microsoft.azure.spring.data.cosmosdb.Constants.ISO_8601_COMPATIBLE_DATE_PATTERN; + +public class MappingCosmosConverter + implements EntityConverter, CosmosPersistentProperty, + Object, CosmosItemProperties>, + ApplicationContextAware { + + protected final MappingContext, + CosmosPersistentProperty> mappingContext; + protected GenericConversionService conversionService; + private ApplicationContext applicationContext; + private ObjectMapper objectMapper; + + public MappingCosmosConverter( + MappingContext, CosmosPersistentProperty> mappingContext, + @Qualifier(Constants.OBJECTMAPPER_BEAN_NAME) ObjectMapper objectMapper) { + this.mappingContext = mappingContext; + this.conversionService = new GenericConversionService(); + this.objectMapper = objectMapper == null ? ObjectMapperFactory.getObjectMapper() : + objectMapper; + } + + @Override + public R read(Class type, CosmosItemProperties cosmosItemProperties) { + if (cosmosItemProperties == null) { + return null; + } + + final CosmosPersistentEntity entity = mappingContext.getPersistentEntity(type); + Assert.notNull(entity, "Entity is null."); + + return readInternal(entity, type, cosmosItemProperties); + } + + private R readInternal(final CosmosPersistentEntity entity, Class type, + final CosmosItemProperties cosmosItemProperties) { + + try { + final CosmosPersistentProperty idProperty = entity.getIdProperty(); + final Object idValue = cosmosItemProperties.id(); + final JSONObject jsonObject = new JSONObject(cosmosItemProperties.toJson()); + + if (idProperty != null) { + // Replace the key id to the actual id field name in domain + jsonObject.remove(Constants.ID_PROPERTY_NAME); + jsonObject.put(idProperty.getName(), idValue); + } + + return objectMapper.readValue(jsonObject.toString(), type); + } catch (IOException e) { + throw new IllegalStateException("Failed to read the source document " + cosmosItemProperties.toJson() + + " to target type " + type, e); + } + } + + @Override + @Deprecated + public void write(Object sourceEntity, CosmosItemProperties document) { + throw new UnsupportedOperationException("The feature is not implemented yet"); + } + + public CosmosItemProperties writeCosmosItemProperties(Object sourceEntity) { + if (sourceEntity == null) { + return null; + } + + final CosmosPersistentEntity persistentEntity = + mappingContext.getPersistentEntity(sourceEntity.getClass()); + + if (persistentEntity == null) { + throw new MappingException("no mapping metadata for entity type: " + sourceEntity.getClass().getName()); + } + + final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity); + final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty(); + final CosmosItemProperties cosmosItemProperties; + + try { + cosmosItemProperties = + new CosmosItemProperties(objectMapper.writeValueAsString(sourceEntity)); + } catch (JsonProcessingException e) { + throw new CosmosDBAccessException("Failed to map document value.", e); + } + + if (idProperty != null) { + final Object value = accessor.getProperty(idProperty); + final String id = value == null ? null : value.toString(); + cosmosItemProperties.id(id); + } + + return cosmosItemProperties; + } + + public ApplicationContext getApplicationContext() { + return this.applicationContext; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Override + public ConversionService getConversionService() { + return conversionService; + } + + public MappingContext, CosmosPersistentProperty> getMappingContext() { + return mappingContext; + } + + + private ConvertingPropertyAccessor getPropertyAccessor(Object entity) { + final CosmosPersistentEntity entityInformation = + mappingContext.getPersistentEntity(entity.getClass()); + + Assert.notNull(entityInformation, "EntityInformation should not be null."); + final PersistentPropertyAccessor accessor = entityInformation.getPropertyAccessor(entity); + return new ConvertingPropertyAccessor(accessor, conversionService); + } + + /** + * Convert a property value to the value stored in CosmosDB + * + * @param fromPropertyValue + * @return + */ + public static Object toCosmosDbValue(Object fromPropertyValue) { + if (fromPropertyValue == null) { + return null; + } + + // com.microsoft.azure.data.cosmos.JsonSerializable#set(String, T) cannot set values for Date and Enum correctly + + if (fromPropertyValue instanceof Date) { + fromPropertyValue = ((Date) fromPropertyValue).getTime(); + } else + if (fromPropertyValue instanceof ZonedDateTime) { + fromPropertyValue = ((ZonedDateTime) fromPropertyValue) + .format(DateTimeFormatter.ofPattern(ISO_8601_COMPATIBLE_DATE_PATTERN)); + } else if (fromPropertyValue instanceof Enum) { + fromPropertyValue = fromPropertyValue.toString(); + } + + return fromPropertyValue; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java new file mode 100644 index 000000000000..e4c03564d569 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.convert; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; + +public class ObjectMapperFactory { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + OBJECT_MAPPER.registerModule(new ParameterNamesModule()) + .registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()); + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + public static ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java new file mode 100644 index 000000000000..932e94ac94e5 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java @@ -0,0 +1,217 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.generator; + +import com.azure.data.cosmos.SqlParameterList; +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.exception.IllegalQueryException; +import org.javatuples.Pair; +import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter.toCosmosDbValue; + +public abstract class AbstractQueryGenerator { + + protected AbstractQueryGenerator() { + } + + private String generateQueryParameter(@NonNull String subject) { + return subject.replaceAll("\\.", "_"); // user.name is not valid sql parameter identifier. + } + + private String generateUnaryQuery(@NonNull Criteria criteria) { + Assert.isTrue(criteria.getSubjectValues().isEmpty(), "Unary criteria should have no one subject value"); + Assert.isTrue(CriteriaType.isUnary(criteria.getType()), "Criteria type should be unary operation"); + final String subject = criteria.getSubject(); + + if (CriteriaType.isFunction(criteria.getType())) { + return String.format("%s(r.%s)", criteria.getType().getSqlKeyword(), subject); + } else { + return String.format("r.%s %s", subject, criteria.getType().getSqlKeyword()); + } + } + + private String generateBinaryQuery(@NonNull Criteria criteria, @NonNull List> parameters) { + Assert.isTrue(criteria.getSubjectValues().size() == 1, "Binary criteria should have only one subject value"); + Assert.isTrue(CriteriaType.isBinary(criteria.getType()), "Criteria type should be binary operation"); + + final String subject = criteria.getSubject(); + final Object subjectValue = toCosmosDbValue(criteria.getSubjectValues().get(0)); + final String parameter = generateQueryParameter(subject); + + parameters.add(Pair.with(parameter, subjectValue)); + + if (CriteriaType.isFunction(criteria.getType())) { + return String.format("%s(r.%s, @%s)", criteria.getType().getSqlKeyword(), subject, parameter); + } else { + return String.format("r.%s %s @%s", subject, criteria.getType().getSqlKeyword(), parameter); + } + } + + private String generateBetween(@NonNull Criteria criteria, @NonNull List> parameters) { + final String subject = criteria.getSubject(); + final Object value1 = toCosmosDbValue(criteria.getSubjectValues().get(0)); + final Object value2 = toCosmosDbValue(criteria.getSubjectValues().get(1)); + final String subject1 = subject + "start"; + final String subject2 = subject + "end"; + final String parameter1 = generateQueryParameter(subject1); + final String parameter2 = generateQueryParameter(subject2); + final String keyword = criteria.getType().getSqlKeyword(); + + parameters.add(Pair.with(parameter1, value1)); + parameters.add(Pair.with(parameter2, value2)); + + return String.format("(r.%s %s @%s AND @%s)", subject, keyword, parameter1, parameter2); + } + + private String generateClosedQuery(@NonNull String left, @NonNull String right, CriteriaType type) { + Assert.isTrue(CriteriaType.isClosed(type) && CriteriaType.isBinary(type), + "Criteria type should be binary and closure operation"); + + return String.join(" ", left, type.getSqlKeyword(), right); + } + + @SuppressWarnings("unchecked") + private String generateInQuery(Criteria criteria) { + Assert.isTrue(criteria.getSubjectValues().size() == 1, "Criteria should have only one subject value"); + if (!(criteria.getSubjectValues().get(0) instanceof Collection)) { + throw new IllegalQueryException("IN keyword requires Collection type in parameters"); + } + final List inRangeValues = new ArrayList<>(); + final Collection values = (Collection) criteria.getSubjectValues().get(0); + + values.forEach(o -> { + if (o instanceof Integer || o instanceof Long) { + inRangeValues.add(String.format("%d", o)); + } else if (o instanceof String) { + inRangeValues.add(String.format("'%s'", (String) o)); + } else if (o instanceof Boolean) { + inRangeValues.add(String.format("%b", (Boolean) o)); + } else { + throw new IllegalQueryException("IN keyword Range only support Number and String type."); + } + }); + + final String inRange = String.join(",", inRangeValues); + return String.format("r.%s %s (%s)", criteria.getSubject(), criteria.getType().getSqlKeyword(), inRange); + } + + private String generateQueryBody(@NonNull Criteria criteria, @NonNull List> parameters) { + final CriteriaType type = criteria.getType(); + + switch (type) { + case ALL: + return ""; + case IN: + case NOT_IN: + return generateInQuery(criteria); + case BETWEEN: + return generateBetween(criteria, parameters); + case IS_NULL: + case IS_NOT_NULL: + case FALSE: + case TRUE: + return generateUnaryQuery(criteria); + case IS_EQUAL: + case NOT: + case BEFORE: + case AFTER: + case LESS_THAN: + case LESS_THAN_EQUAL: + case GREATER_THAN: + case GREATER_THAN_EQUAL: + case CONTAINING: + case ENDS_WITH: + case STARTS_WITH: + return generateBinaryQuery(criteria, parameters); + case AND: + case OR: + Assert.isTrue(criteria.getSubCriteria().size() == 2, "criteria should have two SubCriteria"); + + final String left = generateQueryBody(criteria.getSubCriteria().get(0), parameters); + final String right = generateQueryBody(criteria.getSubCriteria().get(1), parameters); + + return generateClosedQuery(left, right, type); + default: + throw new UnsupportedOperationException("unsupported Criteria type: " + type); + } + } + + /** + * Generate a query body for interface QuerySpecGenerator. + * The query body compose of Sql query String and its' parameters. + * The parameters organized as a list of Pair, for each pair compose parameter name and value. + * + * @param query the representation for query method. + * @return A pair tuple compose of Sql query. + */ + @NonNull + private Pair>> generateQueryBody(@NonNull DocumentQuery query) { + final List> parameters = new ArrayList<>(); + String queryString = this.generateQueryBody(query.getCriteria(), parameters); + + if (StringUtils.hasText(queryString)) { + queryString = String.join(" ", "WHERE", queryString); + } + + return Pair.with(queryString, parameters); + } + + private String getParameter(@NonNull Sort.Order order) { + Assert.isTrue(!order.isIgnoreCase(), "Ignore case is not supported"); + + final String direction = order.isDescending() ? "DESC" : "ASC"; + + return String.format("r.%s %s", order.getProperty(), direction); + } + + private String generateQuerySort(@NonNull Sort sort) { + if (sort.isUnsorted()) { + return ""; + } + + final String queryTail = "ORDER BY"; + final List subjects = sort.stream().map(this::getParameter).collect(Collectors.toList()); + + return queryTail + " " + String.join(",", subjects); + } + + @NonNull + private String generateQueryTail(@NonNull DocumentQuery query) { + final List queryTails = new ArrayList<>(); + + queryTails.add(generateQuerySort(query.getSort())); + + return String.join(" ", queryTails.stream().filter(StringUtils::hasText).collect(Collectors.toList())); + } + + + protected SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query, + @NonNull String queryHead) { + final Pair>> queryBody = generateQueryBody(query); + final String queryString = String.join(" ", queryHead, queryBody.getValue0(), generateQueryTail(query)); + final List> parameters = queryBody.getValue1(); + final SqlParameterList sqlParameters = + new SqlParameterList(); + + sqlParameters.addAll( + parameters.stream() + .map(p -> new com.azure.data.cosmos.SqlParameter("@" + p.getValue0(), + toCosmosDbValue(p.getValue1()))) + .collect(Collectors.toList()) + ); + + return new SqlQuerySpec(queryString, sqlParameters); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java new file mode 100644 index 000000000000..9d02ed74c025 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.generator; + +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; + +public class CountQueryGenerator extends AbstractQueryGenerator implements QuerySpecGenerator { + + @Override + public SqlQuerySpec generateCosmos(DocumentQuery query) { + return super.generateCosmosQuery(query, "SELECT VALUE COUNT(1) FROM r"); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java new file mode 100644 index 000000000000..349b072acac4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.generator; + +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; + +public class FindQuerySpecGenerator extends AbstractQueryGenerator implements QuerySpecGenerator { + + public FindQuerySpecGenerator() { + } + + @Override + public SqlQuerySpec generateCosmos(DocumentQuery query) { + return super.generateCosmosQuery(query, "SELECT * FROM ROOT r"); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java new file mode 100644 index 000000000000..dcdd2e8d8257 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.generator; + +import com.azure.data.cosmos.SqlQuerySpec; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; + +public interface QuerySpecGenerator { + + /** + * Generate the SqlQuerySpec for cosmosDB client. + * @param query tree structured query condition. + * @return SqlQuerySpec executed by cosmos client. + */ + SqlQuerySpec generateCosmos(DocumentQuery query); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java new file mode 100644 index 000000000000..12e69c6f0840 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.expression.BeanFactoryAccessor; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.util.TypeInformation; +import org.springframework.expression.spel.support.StandardEvaluationContext; + + +public class BasicCosmosPersistentEntity extends BasicPersistentEntity + implements CosmosPersistentEntity, ApplicationContextAware { + + private final StandardEvaluationContext context; + + public BasicCosmosPersistentEntity(TypeInformation typeInformation) { + super(typeInformation); + this.context = new StandardEvaluationContext(); + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context.addPropertyAccessor(new BeanFactoryAccessor()); + context.setBeanResolver(new BeanFactoryResolver(applicationContext)); + context.setRootObject(applicationContext); + } + + public String getCollection() { + return ""; + } + + @Override + public String getContainer() { + return ""; + } + + @Override + public String getLanguage() { + return ""; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java new file mode 100644 index 000000000000..fc94b094e8c3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; +import org.springframework.data.mapping.model.Property; +import org.springframework.data.mapping.model.SimpleTypeHolder; + + +public class BasicCosmosPersistentProperty extends AnnotationBasedPersistentProperty + implements CosmosPersistentProperty { + + public BasicCosmosPersistentProperty(Property property, CosmosPersistentEntity owner, + SimpleTypeHolder simpleTypeHolder) { + super(property, owner, simpleTypeHolder); + } + + @Override + protected Association createAssociation() { + return new Association<>(this, null); + } + + @Override + public boolean isIdProperty() { + + if (super.isIdProperty()) { + return true; + } + + return getName().equals(Constants.ID_PROPERTY_NAME); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java new file mode 100644 index 000000000000..0f92ab6fb43d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import org.springframework.context.ApplicationContext; +import org.springframework.data.mapping.context.AbstractMappingContext; +import org.springframework.data.mapping.model.Property; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.TypeInformation; + + +public class CosmosMappingContext + extends AbstractMappingContext, CosmosPersistentProperty> { + + private ApplicationContext context; + + @Override + protected BasicCosmosPersistentEntity createPersistentEntity(TypeInformation typeInformation) { + final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity<>(typeInformation); + + if (context != null) { + entity.setApplicationContext(context); + } + return entity; + } + + @Override + public CosmosPersistentProperty createPersistentProperty(Property property, + BasicCosmosPersistentEntity owner, + SimpleTypeHolder simpleTypeHolder) { + return new BasicCosmosPersistentProperty(property, owner, simpleTypeHolder); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.context = applicationContext; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java new file mode 100644 index 000000000000..1f78834085f2 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import org.springframework.data.mapping.PersistentEntity; + + +public interface CosmosPersistentEntity extends PersistentEntity { + + @Deprecated + String getCollection(); + + String getContainer(); + + String getLanguage(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java new file mode 100644 index 000000000000..33610e291715 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import org.springframework.data.mapping.PersistentProperty; + + +public interface CosmosPersistentProperty extends PersistentProperty { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java new file mode 100644 index 000000000000..5a7ff3c06957 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import org.springframework.data.annotation.Persistent; + +import java.lang.annotation.*; + +@Persistent +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Document { + + String collection() default Constants.DEFAULT_COLLECTION_NAME; + + String ru() default Constants.DEFAULT_REQUEST_UNIT; + + int timeToLive() default Constants.DEFAULT_TIME_TO_LIVE; + + boolean autoCreateCollection() default Constants.DEFAULT_AUTO_CREATE_CONTAINER; +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java new file mode 100644 index 000000000000..a64cf437f54c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import com.azure.data.cosmos.IndexingMode; +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import org.springframework.data.annotation.Persistent; + +import java.lang.annotation.*; + +@Persistent +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface DocumentIndexingPolicy { + boolean automatic() default Constants.DEFAULT_INDEXINGPOLICY_AUTOMATIC; + + IndexingMode mode() default IndexingMode.CONSISTENT; // Enum is not really compile time constant + + String[] includePaths() default {}; + + String[] excludePaths() default {}; +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java new file mode 100644 index 000000000000..54281da598c6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface PartitionKey { + + /** + * The name of the partition key if the serialized attribute name differs from the field name + * + * @return + */ + String value() default ""; +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java new file mode 100644 index 000000000000..730d7142332e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.Objects; + +public class CosmosPageImpl extends PageImpl { + + private static final long serialVersionUID = 5294396337522314504L; + + // For any query, CosmosDB returns documents less than or equal to page size + // Depending on the number of RUs, the number of returned documents can change + // Storing the offset of current page, helps to check hasNext and next values + private long offset; + + public CosmosPageImpl(List content, Pageable pageable, long total) { + super(content, pageable, total); + this.offset = pageable.getOffset(); + } + + @Override + public int getTotalPages() { + return super.getTotalPages(); + } + + @Override + public long getTotalElements() { + return super.getTotalElements(); + } + + @Override + public boolean hasNext() { + return this.offset + getContent().size() < getTotalElements(); + } + + @Override + public boolean isLast() { + return super.isLast(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + final CosmosPageImpl that = (CosmosPageImpl) o; + return offset == that.offset; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), offset); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java new file mode 100644 index 000000000000..58a2dc34c716 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import com.azure.data.cosmos.FeedResponse; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +/** + * CosmosPageRequest representing page request during pagination query, field + * {@link FeedResponse#continuationToken()} response continuation token} is saved + * to help query next page. + *

+ * The requestContinuation token should be saved after each request and reused in later queries. + */ +public class CosmosPageRequest extends PageRequest { + private static final long serialVersionUID = 6093304300037688375L; + + private long offset; + + // Request continuation token used to resume query + private String requestContinuation; + + public CosmosPageRequest(int page, int size, String requestContinuation) { + super(page, size, Sort.unsorted()); + this.requestContinuation = requestContinuation; + } + + public CosmosPageRequest(int page, int size, String requestContinuation, Sort sort) { + super(page, size, sort); + this.requestContinuation = requestContinuation; + } + + private CosmosPageRequest(long offset, int page, int size, String requestContinuation) { + super(page, size, Sort.unsorted()); + this.offset = offset; + this.requestContinuation = requestContinuation; + } + + private CosmosPageRequest(long offset, int page, int size, String requestContinuation, + Sort sort) { + super(page, size, sort); + this.offset = offset; + this.requestContinuation = requestContinuation; + } + + public static CosmosPageRequest of(int page, int size, String requestContinuation, Sort sort) { + return new CosmosPageRequest(0, page, size, requestContinuation, sort); + } + + public static CosmosPageRequest of(long offset, int page, int size, String requestContinuation, Sort sort) { + return new CosmosPageRequest(offset, page, size, requestContinuation, sort); + } + + @Override + public Pageable next() { + return new CosmosPageRequest(this.offset + (long) this.getPageSize(), + this.getPageNumber() + 1, getPageSize(), this.requestContinuation, getSort()); + } + + @Override + public long getOffset() { + return offset; + } + + public String getRequestContinuation() { + return this.requestContinuation; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + + result = 31 * result + (requestContinuation != null ? requestContinuation.hashCode() : 0); + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof CosmosPageRequest)) { + return false; + } + + final CosmosPageRequest that = (CosmosPageRequest) obj; + + final boolean continuationTokenEquals = requestContinuation != null ? + requestContinuation.equals(that.requestContinuation) : that.requestContinuation == null; + + return continuationTokenEquals && super.equals(that); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java new file mode 100644 index 000000000000..2f4c2ab64622 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import org.springframework.lang.NonNull; + +import java.util.ArrayList; +import java.util.List; + +public class Criteria { + + private String subject; + private List subjectValues; + private final CriteriaType type; + private final List subCriteria; + + public String getSubject() { + return subject; + } + + public List getSubjectValues() { + return subjectValues; + } + + public CriteriaType getType() { + return type; + } + + public List getSubCriteria() { + return subCriteria; + } + + private Criteria(CriteriaType type) { + this.type = type; + this.subCriteria = new ArrayList<>(); + } + + public static Criteria getInstance(CriteriaType type, @NonNull String subject, @NonNull List values) { + final Criteria criteria = new Criteria(type); + + criteria.subject = subject; + criteria.subjectValues = values; + + return criteria; + } + + public static Criteria getInstance(CriteriaType type, @NonNull Criteria left, @NonNull Criteria right) { + final Criteria criteria = new Criteria(type); + + criteria.subCriteria.add(left); + criteria.subCriteria.add(right); + + return criteria; + } + + public static Criteria getInstance(CriteriaType type) { + return new Criteria(type); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java new file mode 100644 index 000000000000..35562acab43d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import org.springframework.lang.NonNull; +import org.springframework.data.repository.query.parser.Part; + +import java.beans.ConstructorProperties; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum CriteriaType { + + ALL(""), + IS_EQUAL("="), + OR("OR"), + AND("AND"), + NOT("<>"), + BEFORE("<"), + AFTER(">"), + IN("IN"), + NOT_IN("NOT IN"), + IS_NULL("IS_NULL"), + IS_NOT_NULL("NOT IS_NULL"), + LESS_THAN("<"), + LESS_THAN_EQUAL("<="), + GREATER_THAN(">"), + GREATER_THAN_EQUAL(">="), + CONTAINING("CONTAINS"), + ENDS_WITH("ENDSWITH"), + STARTS_WITH("STARTSWITH"), + TRUE("= true"), + FALSE("= false"), + BETWEEN("BETWEEN"); + + private String sqlKeyword; + + private static final Map PART_TREE_TYPE_TO_CRITERIA; + + static { + final Map map = new HashMap<>(); + + map.put(Part.Type.NEGATING_SIMPLE_PROPERTY, CriteriaType.NOT); + map.put(Part.Type.IS_NULL, CriteriaType.IS_NULL); + map.put(Part.Type.IS_NOT_NULL, CriteriaType.IS_NOT_NULL); + map.put(Part.Type.SIMPLE_PROPERTY, CriteriaType.IS_EQUAL); + map.put(Part.Type.BEFORE, CriteriaType.BEFORE); + map.put(Part.Type.AFTER, CriteriaType.AFTER); + map.put(Part.Type.IN, CriteriaType.IN); + map.put(Part.Type.NOT_IN, CriteriaType.NOT_IN); + map.put(Part.Type.GREATER_THAN, CriteriaType.GREATER_THAN); + map.put(Part.Type.CONTAINING, CriteriaType.CONTAINING); + map.put(Part.Type.ENDING_WITH, CriteriaType.ENDS_WITH); + map.put(Part.Type.STARTING_WITH, CriteriaType.STARTS_WITH); + map.put(Part.Type.GREATER_THAN_EQUAL, CriteriaType.GREATER_THAN_EQUAL); + map.put(Part.Type.LESS_THAN, CriteriaType.LESS_THAN); + map.put(Part.Type.LESS_THAN_EQUAL, CriteriaType.LESS_THAN_EQUAL); + map.put(Part.Type.TRUE, CriteriaType.TRUE); + map.put(Part.Type.FALSE, CriteriaType.FALSE); + map.put(Part.Type.BETWEEN, CriteriaType.BETWEEN); + + PART_TREE_TYPE_TO_CRITERIA = Collections.unmodifiableMap(map); + } + + @ConstructorProperties({"sqlKeyword"}) + CriteriaType(String sqlKeyword) { + this.sqlKeyword = sqlKeyword; + } + + public String getSqlKeyword() { + return sqlKeyword; + } + + /** + * Check if PartType is NOT supported. + * + * @param partType + * @return True if unsupported, or false. + */ + public static boolean isPartTypeUnSupported(@NonNull Part.Type partType) { + return !isPartTypeSupported(partType); + } + + /** + * Check if PartType is supported. + * + * @param partType + * @return True if supported, or false. + */ + public static boolean isPartTypeSupported(@NonNull Part.Type partType) { + return PART_TREE_TYPE_TO_CRITERIA.containsKey(partType); + } + + public static CriteriaType toCriteriaType(@NonNull Part.Type partType) { + final CriteriaType criteriaType = PART_TREE_TYPE_TO_CRITERIA.get(partType); + + if (criteriaType == null) { + throw new UnsupportedOperationException("Unsupported part type: " + partType); + } + + return criteriaType; + } + + /** + * Check if CriteriaType operation is closure, with format of (A ops A -> A). + * Example: AND, OR. + * + * @param type + * @return True if match, or false. + */ + public static boolean isClosed(CriteriaType type) { + switch (type) { + case AND: + case OR: + return true; + default: + return false; + } + } + + /** + * Check if CriteriaType operation is binary, with format of (A ops A -> B). + * Example: IS_EQUAL, AFTER. + * + * @param type + * @return True if match, or false. + */ + public static boolean isBinary(CriteriaType type) { + switch (type) { + case IN: + case NOT_IN: + case AND: + case OR: + case NOT: + case IS_EQUAL: + case BEFORE: + case AFTER: + case LESS_THAN: + case LESS_THAN_EQUAL: + case GREATER_THAN: + case GREATER_THAN_EQUAL: + case CONTAINING: + case ENDS_WITH: + case STARTS_WITH: + return true; + default: + return false; + } + } + + /** + * Check if CriteriaType operation is a function. + * + * @param type + * @return True if match, or false. + */ + public static boolean isFunction(CriteriaType type) { + switch (type) { + case CONTAINING: + case ENDS_WITH: + case STARTS_WITH: + case IS_NULL: + case IS_NOT_NULL: + return true; + default: + return false; + } + } + + /** + * Check if CriteriaType operation is unary, with format of (ops A -> B). + * + * @param type + * @return True if match, or false. + */ + public static boolean isUnary(CriteriaType type) { + switch (type) { + case IS_NULL: + case IS_NOT_NULL: + case TRUE: + case FALSE: + return true; + default: + return false; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java new file mode 100644 index 000000000000..55cdf70a5978 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for + * license information. + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import java.util.List; +import java.util.Optional; + +public class DocumentQuery { + + private final Criteria criteria; + + private Sort sort = Sort.unsorted(); + + private Pageable pageable = Pageable.unpaged(); + + public DocumentQuery(@NonNull Criteria criteria) { + this.criteria = criteria; + } + + public Criteria getCriteria() { + return criteria; + } + + public Sort getSort() { + return sort; + } + + public Pageable getPageable() { + return pageable; + } + + public DocumentQuery with(@NonNull Sort sort) { + if (sort.isSorted()) { + this.sort = sort.and(this.sort); + } + + return this; + } + + public DocumentQuery with(@NonNull Pageable pageable) { + Assert.notNull(pageable, "pageable should not be null"); + + this.pageable = pageable; + return this; + } + + private boolean isCrossPartitionQuery(@NonNull String keyName) { + Assert.hasText(keyName, "PartitionKey should have text."); + + final Optional criteria = this.getSubjectCriteria(this.criteria, keyName); + + return criteria.map(criteria1 -> criteria1.getType() != CriteriaType.IS_EQUAL).orElse(true); + } + + private boolean hasKeywordOr() { + // If there is OR keyword in DocumentQuery, the top node of Criteria must be OR type. + return this.criteria.getType() == CriteriaType.OR; + } + + /** + * Indicate if DocumentQuery should enable cross partition query. + * + * @param partitionKeys The list of partitionKey names. + * @return + */ + public boolean isCrossPartitionQuery(@NonNull List partitionKeys) { + if (partitionKeys.isEmpty()) { + return true; + } + + return partitionKeys.stream().filter(this::isCrossPartitionQuery) + .findFirst() + .map(p -> true) + .orElse(hasKeywordOr()); + } + + public Optional getCriteriaByType(@NonNull CriteriaType criteriaType) { + return getCriteriaByType(criteriaType, this.criteria); + } + + private Optional getCriteriaByType(@NonNull CriteriaType criteriaType, @NonNull Criteria criteria) { + if (criteria.getType().equals(criteriaType)) { + return Optional.of(criteria); + } + + for (final Criteria subCriteria: criteria.getSubCriteria()) { + if (getCriteriaByType(criteriaType, subCriteria).isPresent()) { + return Optional.of(subCriteria); + } + } + + return Optional.empty(); + } + + private Optional getSubjectCriteria(@NonNull Criteria criteria, @NonNull String keyName) { + if (keyName.equals(criteria.getSubject())) { + return Optional.of(criteria); + } + + final List subCriteriaList = criteria.getSubCriteria(); + + for (final Criteria c : subCriteriaList) { + final Optional subjectCriteria = getSubjectCriteria(c, keyName); + + if (subjectCriteria.isPresent()) { + return subjectCriteria; + } + } + + return Optional.empty(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java new file mode 100644 index 000000000000..262753f211fa --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import org.springframework.dao.DataAccessException; + +public class ConfigurationException extends DataAccessException { + + public ConfigurationException(String msg) { + super(msg); + } + + public ConfigurationException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java new file mode 100644 index 000000000000..4cf4d2cd99e5 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import com.azure.data.cosmos.CosmosClientException; +import org.springframework.dao.DataAccessException; +import org.springframework.lang.Nullable; + +/** + * Public class extending DataAccessException, exposes innerException. + * Every API in {@link com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository} + * and {@link com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository} + * should throw {@link CosmosDBAccessException}. + * innerException refers to the exception thrown by CosmosDB SDK. Callers of repository APIs can + * rely on innerException for any retriable logic, or for more details on the failure of + * the operation. + */ +public class CosmosDBAccessException extends DataAccessException { + + protected final CosmosClientException cosmosClientException; + + public CosmosDBAccessException(String msg) { + super(msg); + this.cosmosClientException = null; + } + + public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) { + super(msg, cause); + if (cause instanceof CosmosClientException) { + this.cosmosClientException = (CosmosClientException) cause; + } else { + this.cosmosClientException = null; + } + } + + public CosmosDBAccessException(@Nullable String msg, @Nullable Exception cause) { + super(msg, cause); + this.cosmosClientException = cause instanceof CosmosClientException + ? (CosmosClientException) cause + : null; + } + + public CosmosClientException getCosmosClientException() { + return cosmosClientException; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java new file mode 100644 index 000000000000..049a153f400c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.internal.HttpConstants; +import org.springframework.util.StringUtils; +import reactor.core.Exceptions; +import reactor.core.publisher.Mono; + +public class CosmosDBExceptionUtils { + + public static Mono exceptionHandler(String message, Throwable throwable) { + if (StringUtils.isEmpty(message)) { + message = "Failed to access cosmosdb database"; + } + // Unwrap the exception in case if it is a reactive exception + final Throwable unwrappedThrowable = Exceptions.unwrap(throwable); + throw new CosmosDBAccessException(message, unwrappedThrowable); + } + + public static Mono findAPIExceptionHandler(String message, Throwable throwable) { + // Unwrap the exception in case if it is a reactive exception + final Throwable unwrappedThrowable = Exceptions.unwrap(throwable); + if (unwrappedThrowable instanceof CosmosClientException) { + final CosmosClientException cosmosClientException = (CosmosClientException) unwrappedThrowable; + if (cosmosClientException.statusCode() == HttpConstants.StatusCodes.NOTFOUND) { + return Mono.empty(); + } + } + return exceptionHandler(message, unwrappedThrowable); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java new file mode 100644 index 000000000000..62583a7d891a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import org.springframework.dao.DataAccessException; +import org.springframework.lang.Nullable; + +public class DatabaseCreationException extends DataAccessException { + public DatabaseCreationException(String msg) { + super(msg); + } + + public DatabaseCreationException(@Nullable String msg, @Nullable Throwable cause) { + super(msg, cause); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java new file mode 100644 index 000000000000..57de1768a46b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import org.springframework.dao.DataAccessException; +import org.springframework.lang.Nullable; + +public class IllegalCollectionException extends DataAccessException { + public IllegalCollectionException(String msg) { + super(msg); + } + + public IllegalCollectionException(@Nullable String msg, @Nullable Throwable cause) { + super(msg, cause); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java new file mode 100644 index 000000000000..c57868b60251 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.exception; + +import org.springframework.dao.DataAccessException; +import org.springframework.lang.Nullable; + +public class IllegalQueryException extends DataAccessException { + public IllegalQueryException(String msg) { + super(msg); + } + + public IllegalQueryException(@Nullable String msg, @Nullable Throwable cause) { + super(msg, cause); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java new file mode 100644 index 000000000000..c830cdc9edd2 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.azure.data.cosmos.PartitionKey; +import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.data.repository.PagingAndSortingRepository; + +import java.io.Serializable; +import java.util.List; +import java.util.Optional; + +@NoRepositoryBean +public interface CosmosRepository extends PagingAndSortingRepository { + + /** + * Retrieves an entity by its id. + * + * @param id must not be {@literal null}. + * @param partitionKey partition key value of entity, must not be null. + * @return the entity with the given id or {@literal Optional#empty()} if none found + * @throws IllegalArgumentException if {@code id} is {@literal null}. + */ + Optional findById(ID id, PartitionKey partitionKey); + + /** + * Deletes an entity by its id and partition key. + * @param id must not be {@literal null}. + * @param partitionKey partition key value of the entity, must not be null. + * @throws IllegalArgumentException in case the given {@code id} is {@literal null}. + */ + void deleteById(ID id, PartitionKey partitionKey); + + /** + * Returns list of items in a specific partition + * @param partitionKey partition key value + * @return list of items with partition key value + */ + List findAll(PartitionKey partitionKey); + +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java new file mode 100644 index 000000000000..b8119eff78f0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.azure.data.cosmos.PartitionKey; +import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.data.repository.reactive.ReactiveSortingRepository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@NoRepositoryBean +public interface ReactiveCosmosRepository extends ReactiveSortingRepository { + + /** + * Retrieves an entity by its id and partition key. + * @param id must not be {@literal null}. + * @param partitionKey partition key value of the entity, must not be null. + * @return {@link Mono} emitting the entity with the given id or {@link Mono#empty()} if none found. + * @throws IllegalArgumentException in case the given {@code id} is {@literal null}. + */ + Mono findById(K id, PartitionKey partitionKey); + + /** + * Deletes an entity by its id and partition key. + * @param id must not be {@literal null}. + * @param partitionKey partition key value of the entity, must not be null. + * @return {@link Mono} emitting the void Mono. + * @throws IllegalArgumentException in case the given {@code id} is {@literal null}. + */ + Mono deleteById(K id, PartitionKey partitionKey); + + /** + * Returns Flux of items in a specific partition + * @param partitionKey partition key value + * @return {@link Flux} of items with partition key value + */ + Flux findAll(PartitionKey partitionKey); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java new file mode 100644 index 000000000000..d3b805a6ba0c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +import java.lang.annotation.Annotation; + + +public class CosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { + + @Override + protected Class getAnnotation() { + return EnableCosmosRepositories.class; + } + + @Override + protected RepositoryConfigurationExtension getExtension() { + return new CosmosRepositoryConfigurationExtension(); + } + + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java new file mode 100644 index 000000000000..f46493f4fd4d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; +import org.springframework.data.repository.config.RepositoryConfigurationSource; +import org.springframework.data.repository.core.RepositoryMetadata; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Collections; + + +public class CosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { + + @Override + public String getModuleName() { + return Constants.COSMOSDB_MODULE_NAME; + } + + @Override + public String getModulePrefix() { + return Constants.COSMOSDB_MODULE_PREFIX; + } + + public String getRepositoryFactoryBeanClassName() { + return CosmosRepositoryFactoryBean.class.getName(); + } + + @Override + protected Collection> getIdentifyingTypes() { + return Collections.>singleton(CosmosRepository.class); + } + + @Override + protected Collection> getIdentifyingAnnotations() { + return Collections.emptyList(); + } + + + @Override + public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) { + super.registerBeansForRoot(registry, config); + + if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) { + final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class); + definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE); + definition.setSource(config.getSource()); + + registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition); + } + } + + @Override + public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) { + super.postProcess(builder, source); + } + + // Overriding this to provide reactive repository support. + @Override + protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) { + // CosmosRepository is the sync repository, and hence returning !isReactiveRepository. + // ReactiveCosmosRepository is reactive repository. + return !metadata.isReactiveRepository(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java new file mode 100644 index 000000000000..270bb1aacbcf --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Import; +import org.springframework.data.repository.config.DefaultRepositoryBaseClass; +import org.springframework.data.repository.query.QueryLookupStrategy; + +import java.lang.annotation.*; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import(CosmosRepositoriesRegistrar.class) +public @interface EnableCosmosRepositories { + + String[] value() default {}; + + String[] basePackages() default {}; + + Class[] basePackageClasses() default {}; + + Filter[] includeFilters() default {}; + + Filter[] excludeFilters() default {}; + + String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX; + + String namedQueriesLocation() default ""; + + QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND; + + Class repositoryFactoryBeanClass() default CosmosRepositoryFactoryBean.class; + + Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; + + boolean considerNestedRepositories() default false; +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java new file mode 100644 index 000000000000..cd22140f59f5 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Import; +import org.springframework.data.repository.config.DefaultRepositoryBaseClass; +import org.springframework.data.repository.query.QueryLookupStrategy; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import(ReactiveCosmosRepositoriesRegistrar.class) +public @interface EnableReactiveCosmosRepositories { + + String[] value() default {}; + + String[] basePackages() default {}; + + Class[] basePackageClasses() default {}; + + Filter[] includeFilters() default {}; + + Filter[] excludeFilters() default {}; + + String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX; + + String namedQueriesLocation() default ""; + + QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND; + + Class repositoryFactoryBeanClass() default ReactiveCosmosRepositoryFactoryBean.class; + + Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; + + boolean considerNestedRepositories() default false; +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java new file mode 100644 index 000000000000..569a2d8666d3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +import java.lang.annotation.Annotation; + + +public class ReactiveCosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { + + @Override + protected Class getAnnotation() { + return EnableReactiveCosmosRepositories.class; + } + + @Override + protected RepositoryConfigurationExtension getExtension() { + return new ReactiveCosmosRepositoryConfigurationExtension(); + } + + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java new file mode 100644 index 000000000000..8926d4917e62 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; +import org.springframework.data.repository.config.RepositoryConfigurationSource; +import org.springframework.data.repository.core.RepositoryMetadata; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Collections; + + +public class ReactiveCosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { + + @Override + public String getModuleName() { + return Constants.COSMOSDB_MODULE_NAME; + } + + @Override + public String getModulePrefix() { + return Constants.COSMOSDB_MODULE_PREFIX; + } + + public String getRepositoryFactoryBeanClassName() { + return ReactiveCosmosRepositoryFactoryBean.class.getName(); + } + + @Override + protected Collection> getIdentifyingTypes() { + return Collections.>singleton(ReactiveCosmosRepository.class); + } + + @Override + protected Collection> getIdentifyingAnnotations() { + return Collections.emptyList(); + } + + + @Override + public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) { + super.registerBeansForRoot(registry, config); + + if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) { + final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class); + definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE); + definition.setSource(config.getSource()); + + registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition); + } + } + + @Override + public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) { + super.postProcess(builder, source); + } + + // Overriding this to provide reactive repository support. + @Override + protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) { + return metadata.isReactiveRepository(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java new file mode 100644 index 000000000000..172bca42f779 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ResultProcessor; + +public abstract class AbstractCosmosQuery implements RepositoryQuery { + + private final CosmosQueryMethod method; + private final CosmosOperations operations; + + public AbstractCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) { + this.method = method; + this.operations = operations; + } + + public Object execute(Object[] parameters) { + final CosmosParameterAccessor accessor = new CosmosParameterParameterAccessor(method, parameters); + final DocumentQuery query = createQuery(accessor); + + final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor); + final String container = ((CosmosEntityMetadata) method.getEntityInformation()).getContainerName(); + + final CosmosQueryExecution execution = getExecution(accessor); + return execution.execute(query, processor.getReturnedType().getDomainType(), container); + } + + + private CosmosQueryExecution getExecution(CosmosParameterAccessor accessor) { + if (isDeleteQuery()) { + return new CosmosQueryExecution.DeleteExecution(operations); + } else if (method.isPageQuery()) { + return new CosmosQueryExecution.PagedExecution(operations, accessor.getPageable()); + } else if (isExistsQuery()) { + return new CosmosQueryExecution.ExistsExecution(operations); + } else { + return new CosmosQueryExecution.MultiEntityExecution(operations); + } + } + + public CosmosQueryMethod getQueryMethod() { + return method; + } + + protected abstract DocumentQuery createQuery(CosmosParameterAccessor accessor); + + protected abstract boolean isDeleteQuery(); + + protected abstract boolean isExistsQuery(); + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java new file mode 100644 index 000000000000..437ce543798e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ResultProcessor; + +public abstract class AbstractReactiveCosmosQuery implements RepositoryQuery { + + private final ReactiveCosmosQueryMethod method; + private final ReactiveCosmosOperations operations; + + public AbstractReactiveCosmosQuery(ReactiveCosmosQueryMethod method, + ReactiveCosmosOperations operations) { + this.method = method; + this.operations = operations; + } + + public Object execute(Object[] parameters) { + final ReactiveCosmosParameterAccessor accessor = + new ReactiveCosmosParameterParameterAccessor(method, parameters); + final DocumentQuery query = createQuery(accessor); + + final ResultProcessor processor = + method.getResultProcessor().withDynamicProjection(accessor); + final String containerName = + ((ReactiveCosmosEntityMetadata) method.getEntityInformation()).getContainerName(); + + final ReactiveCosmosQueryExecution execution = getExecution(accessor); + return execution.execute(query, processor.getReturnedType().getDomainType(), containerName); + } + + + private ReactiveCosmosQueryExecution getExecution(ReactiveCosmosParameterAccessor accessor) { + if (isDeleteQuery()) { + return new ReactiveCosmosQueryExecution.DeleteExecution(operations); + } else if (method.isPageQuery()) { + throw new IllegalArgumentException("Paged Query is not supported by reactive cosmos " + + "db"); + } else if (isExistsQuery()) { + return new ReactiveCosmosQueryExecution.ExistsExecution(operations); + } else { + return new ReactiveCosmosQueryExecution.MultiEntityExecution(operations); + } + } + + public ReactiveCosmosQueryMethod getQueryMethod() { + return method; + } + + protected abstract DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor); + + protected abstract boolean isDeleteQuery(); + + protected abstract boolean isExistsQuery(); + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java new file mode 100644 index 000000000000..29ce6a4c4923 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.core.EntityMetadata; + +public interface CosmosEntityMetadata extends EntityMetadata { + + /** + * Use getContainerName() instead + * @return container name + */ + @Deprecated + String getCollectionName(); + + String getContainerName(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java new file mode 100644 index 000000000000..cebfc1f6a57e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.core.MethodParameter; +import org.springframework.data.repository.query.Parameter; + +public class CosmosParameter extends Parameter { + + public CosmosParameter(MethodParameter parameter) { + super(parameter); + } + + @Override + public boolean isSpecialParameter() { + return super.isSpecialParameter(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java new file mode 100644 index 000000000000..26916c55cf2e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.query.ParameterAccessor; + +public interface CosmosParameterAccessor extends ParameterAccessor { + Object[] getValues(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java new file mode 100644 index 000000000000..5a0ce5186b88 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.query.ParametersParameterAccessor; + +import java.util.Arrays; +import java.util.List; + +public class CosmosParameterParameterAccessor extends ParametersParameterAccessor + implements CosmosParameterAccessor { + + private final List values; + + public CosmosParameterParameterAccessor(CosmosQueryMethod method, Object[] values) { + super(method.getParameters(), values); + + this.values = Arrays.asList(values); + } + + @Override + public Object[] getValues() { + return values.toArray(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java new file mode 100644 index 000000000000..39017da4d9df --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.core.MethodParameter; +import org.springframework.data.repository.query.Parameters; + +import java.lang.reflect.Method; +import java.util.List; + +public class CosmosParameters extends Parameters { + + public CosmosParameters(Method method) { + super(method); + } + + private CosmosParameters(List parameters) { + super(parameters); + } + + @Override + protected CosmosParameters createFrom(List parameters) { + return new CosmosParameters(parameters); + } + + @Override + protected CosmosParameter createParameter(MethodParameter parameter) { + return new CosmosParameter(parameter); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java new file mode 100644 index 000000000000..df8fb6007d82 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.data.domain.Sort; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.query.parser.AbstractQueryCreator; +import org.springframework.data.repository.query.parser.Part; +import org.springframework.data.repository.query.parser.PartTree; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +// TODO: String based query, based on how cosmosdb provides. +// StringCosmosQuery class, +// How to bind values to the query. if CosmosDb already has binding capability, if not we would have to do it here in +// some creative way.query creator are associated with part tree queries, +public class CosmosQueryCreator extends AbstractQueryCreator { + + private final MappingContext mappingContext; + + public CosmosQueryCreator(PartTree tree, CosmosParameterAccessor accessor, + MappingContext mappingContext) { + super(tree, accessor); + + this.mappingContext = mappingContext; + } + + private String getSubject(@NonNull Part part) { + String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath(); + final Class domainType = part.getProperty().getOwningType().getType(); + + @SuppressWarnings("unchecked") final CosmosEntityInformation information = + new CosmosEntityInformation(domainType); + + if (information.getIdField().getName().equals(subject)) { + subject = Constants.ID_PROPERTY_NAME; + } + + return subject; + } + + @Override // Note (panli): side effect here, this method will change the iterator status of parameters. + protected Criteria create(Part part, Iterator parameters) { + final Part.Type type = part.getType(); + final String subject = getSubject(part); + final List values = new ArrayList<>(); + + if (CriteriaType.isPartTypeUnSupported(type)) { + throw new UnsupportedOperationException("Unsupported keyword: " + type); + } + + for (int i = 0; i < part.getNumberOfArguments(); i++) { + Assert.isTrue(parameters.hasNext(), "should not reach the end of iterator"); + values.add(parameters.next()); + } + + return Criteria.getInstance(CriteriaType.toCriteriaType(type), subject, values); + } + + @Override + protected Criteria and(@NonNull Part part, @NonNull Criteria base, @NonNull Iterator parameters) { + final Criteria right = this.create(part, parameters); + + return Criteria.getInstance(CriteriaType.AND, base, right); + } + + @Override + protected Criteria or(@NonNull Criteria base, @NonNull Criteria criteria) { + return Criteria.getInstance(CriteriaType.OR, base, criteria); + } + + @Override + protected DocumentQuery complete(@NonNull Criteria criteria, @NonNull Sort sort) { + return new DocumentQuery(criteria).with(sort); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java new file mode 100644 index 000000000000..4b34f6516a3c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import org.springframework.data.domain.Pageable; + +public interface CosmosQueryExecution { + Object execute(DocumentQuery query, Class type, String container); + + final class ContainerExecution implements CosmosQueryExecution { + + private final CosmosOperations operations; + + public ContainerExecution(CosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.getContainerName(type); + } + } + + final class MultiEntityExecution implements CosmosQueryExecution { + + private final CosmosOperations operations; + + public MultiEntityExecution(CosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.find(query, type, container); + } + } + + final class ExistsExecution implements CosmosQueryExecution { + + private final CosmosOperations operations; + + public ExistsExecution(CosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.exists(query, type, container); + } + } + + final class DeleteExecution implements CosmosQueryExecution { + + private final CosmosOperations operations; + + public DeleteExecution(CosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.delete(query, type, container); + } + } + + final class PagedExecution implements CosmosQueryExecution { + private final CosmosOperations operations; + private final Pageable pageable; + + public PagedExecution(CosmosOperations operations, Pageable pageable) { + this.operations = operations; + this.pageable = pageable; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + if (pageable.getPageNumber() != 0 && !(pageable instanceof CosmosPageRequest)) { + throw new IllegalStateException("Not the first page but Pageable is not a valid " + + "CosmosPageRequest, requestContinuation is required for non first page request"); + } + + query.with(pageable); + + return operations.paginationQuery(query, type, container); + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java new file mode 100644 index 000000000000..3241c0602ab6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.EntityMetadata; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; + +import java.lang.reflect.Method; + +public class CosmosQueryMethod extends QueryMethod { + + private CosmosEntityMetadata metadata; + + public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { + super(method, metadata, factory); + } + + @Override + @SuppressWarnings("unchecked") + public EntityMetadata getEntityInformation() { + final Class domainType = (Class) getDomainClass(); + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(domainType); + + this.metadata = new SimpleCosmosEntityMetadata(domainType, entityInformation); + return this.metadata; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java new file mode 100644 index 000000000000..2a5251aec302 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty; +import org.apache.commons.lang3.NotImplementedException; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.repository.query.parser.PartTree; + +public class PartTreeCosmosQuery extends AbstractCosmosQuery { + + private final PartTree tree; + private final MappingContext mappingContext; + private final ResultProcessor processor; + + public PartTreeCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) { + super(method, operations); + + this.processor = method.getResultProcessor(); + this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType()); + this.mappingContext = operations.getConverter().getMappingContext(); + } + + @Override + protected DocumentQuery createQuery(CosmosParameterAccessor accessor) { + final CosmosQueryCreator creator = new CosmosQueryCreator(tree, accessor, mappingContext); + + final DocumentQuery query = creator.createQuery(); + + if (tree.isLimiting()) { + throw new NotImplementedException("Limiting is not supported."); + } + + return query; + } + + @Override + protected boolean isDeleteQuery() { + return tree.isDelete(); + } + + @Override + protected boolean isExistsQuery() { + return tree.isExistsProjection(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java new file mode 100644 index 000000000000..5a76d5055a7f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import org.apache.commons.lang3.NotImplementedException; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.repository.query.parser.PartTree; + +public class PartTreeReactiveCosmosQuery extends AbstractReactiveCosmosQuery { + + private final PartTree tree; + private final MappingContext mappingContext; + private final ResultProcessor processor; + + public PartTreeReactiveCosmosQuery(ReactiveCosmosQueryMethod method, ReactiveCosmosOperations operations) { + super(method, operations); + + this.processor = method.getResultProcessor(); + this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType()); + this.mappingContext = operations.getConverter().getMappingContext(); + } + + @Override + protected DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor) { + final ReactiveCosmosQueryCreator creator = new ReactiveCosmosQueryCreator(tree, accessor, mappingContext); + + final DocumentQuery query = creator.createQuery(); + + if (tree.isLimiting()) { + throw new NotImplementedException("Limiting is not supported."); + } + + return query; + } + + @Override + protected boolean isDeleteQuery() { + return tree.isDelete(); + } + + @Override + protected boolean isExistsQuery() { + return tree.isExistsProjection(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java new file mode 100644 index 000000000000..b35a893d1234 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.core.EntityMetadata; + +public interface ReactiveCosmosEntityMetadata extends EntityMetadata { + @Deprecated + String getCollectionName(); + + String getContainerName(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java new file mode 100644 index 000000000000..e9cbccbb0da9 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.query.ParameterAccessor; + +public interface ReactiveCosmosParameterAccessor extends ParameterAccessor { + Object[] getValues(); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java new file mode 100644 index 000000000000..68157756fbe0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import org.springframework.data.repository.query.ParametersParameterAccessor; + +import java.util.Arrays; +import java.util.List; + +public class ReactiveCosmosParameterParameterAccessor extends ParametersParameterAccessor + implements ReactiveCosmosParameterAccessor { + + private final List values; + + public ReactiveCosmosParameterParameterAccessor(ReactiveCosmosQueryMethod method, Object[] values) { + super(method.getParameters(), values); + + this.values = Arrays.asList(values); + } + + @Override + public Object[] getValues() { + return values.toArray(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java new file mode 100644 index 000000000000..66e46954db8b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.data.domain.Sort; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.query.parser.AbstractQueryCreator; +import org.springframework.data.repository.query.parser.Part; +import org.springframework.data.repository.query.parser.PartTree; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ReactiveCosmosQueryCreator extends AbstractQueryCreator { + + private final MappingContext mappingContext; + + public ReactiveCosmosQueryCreator(PartTree tree, ReactiveCosmosParameterAccessor accessor, + MappingContext mappingContext) { + super(tree, accessor); + + this.mappingContext = mappingContext; + } + + private String getSubject(@NonNull Part part) { + String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath(); + final Class domainType = part.getProperty().getOwningType().getType(); + + @SuppressWarnings("unchecked") final CosmosEntityInformation information = + new CosmosEntityInformation(domainType); + + if (information.getIdField().getName().equals(subject)) { + subject = Constants.ID_PROPERTY_NAME; + } + + return subject; + } + + @Override // Note (panli): side effect here, this method will change the iterator status of parameters. + protected Criteria create(Part part, Iterator parameters) { + final Part.Type type = part.getType(); + final String subject = getSubject(part); + final List values = new ArrayList<>(); + + if (CriteriaType.isPartTypeUnSupported(type)) { + throw new UnsupportedOperationException("Unsupported keyword: " + type); + } + + for (int i = 0; i < part.getNumberOfArguments(); i++) { + Assert.isTrue(parameters.hasNext(), "should not reach the end of iterator"); + values.add(parameters.next()); + } + + return Criteria.getInstance(CriteriaType.toCriteriaType(type), subject, values); + } + + @Override + protected Criteria and(@NonNull Part part, @NonNull Criteria base, @NonNull Iterator parameters) { + final Criteria right = this.create(part, parameters); + + return Criteria.getInstance(CriteriaType.AND, base, right); + } + + @Override + protected Criteria or(@NonNull Criteria base, @NonNull Criteria criteria) { + return Criteria.getInstance(CriteriaType.OR, base, criteria); + } + + @Override + protected DocumentQuery complete(@NonNull Criteria criteria, @NonNull Sort sort) { + return new DocumentQuery(criteria).with(sort); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java new file mode 100644 index 000000000000..5ef95b26c625 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; + +public interface ReactiveCosmosQueryExecution { + Object execute(DocumentQuery query, Class type, String container); + + final class ContainerExecution implements ReactiveCosmosQueryExecution { + + private final ReactiveCosmosOperations operations; + + public ContainerExecution(ReactiveCosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.getContainerName(type); + } + } + + final class MultiEntityExecution implements ReactiveCosmosQueryExecution { + + private final ReactiveCosmosOperations operations; + + public MultiEntityExecution(ReactiveCosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.find(query, type, container); + } + } + + final class ExistsExecution implements ReactiveCosmosQueryExecution { + + private final ReactiveCosmosOperations operations; + + public ExistsExecution(ReactiveCosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.exists(query, type, container); + } + } + + final class DeleteExecution implements ReactiveCosmosQueryExecution { + + private final ReactiveCosmosOperations operations; + + public DeleteExecution(ReactiveCosmosOperations operations) { + this.operations = operations; + } + + @Override + public Object execute(DocumentQuery query, Class type, String container) { + return operations.delete(query, type, container); + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java new file mode 100644 index 000000000000..25018802eb64 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.EntityMetadata; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; + +import java.lang.reflect.Method; + +public class ReactiveCosmosQueryMethod extends QueryMethod { + + private ReactiveCosmosEntityMetadata metadata; + + public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { + super(method, metadata, factory); + } + + @Override + @SuppressWarnings("unchecked") + public EntityMetadata getEntityInformation() { + final Class domainType = (Class) getDomainClass(); + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(domainType); + + this.metadata = new SimpleReactiveCosmosEntityMetadata(domainType, entityInformation); + return this.metadata; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java new file mode 100644 index 000000000000..4e95b54b7f6a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.util.Assert; + +public class SimpleCosmosEntityMetadata implements CosmosEntityMetadata { + + private final Class type; + private final CosmosEntityInformation entityInformation; + + public SimpleCosmosEntityMetadata(Class type, CosmosEntityInformation entityInformation) { + Assert.notNull(type, "type must not be null!"); + Assert.notNull(entityInformation, "entityInformation must not be null!"); + + this.type = type; + this.entityInformation = entityInformation; + } + + public Class getJavaType() { + return type; + } + + public String getCollectionName() { + return entityInformation.getContainerName(); + } + + public String getContainerName() { + return entityInformation.getContainerName(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java new file mode 100644 index 000000000000..930bbf005596 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.query; + +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.springframework.util.Assert; + +public class SimpleReactiveCosmosEntityMetadata implements ReactiveCosmosEntityMetadata { + + private final Class type; + private final CosmosEntityInformation entityInformation; + + public SimpleReactiveCosmosEntityMetadata(Class type, CosmosEntityInformation entityInformation) { + Assert.notNull(type, "type must not be null!"); + Assert.notNull(entityInformation, "entityInformation must not be null!"); + + this.type = type; + this.entityInformation = entityInformation; + } + + public Class getJavaType() { + return type; + } + + public String getCollectionName() { + return entityInformation.getContainerName(); + } + + @Override + public String getContainerName() { + return entityInformation.getContainerName(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java new file mode 100644 index 000000000000..fcaad6bbf7bb --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.azure.data.cosmos.ExcludedPath; +import com.azure.data.cosmos.IncludedPath; +import com.azure.data.cosmos.IndexingMode; +import com.azure.data.cosmos.IndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.apache.commons.lang3.reflect.FieldUtils; + +import org.json.JSONObject; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.repository.core.support.AbstractEntityInformation; +import org.springframework.lang.NonNull; +import org.springframework.util.ReflectionUtils; + +import static com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver.resolveExpression; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + + +public class CosmosEntityInformation extends AbstractEntityInformation { + + private static final String ETAG = "_etag"; + private Field id; + private Field partitionKeyField; + private String containerName; + private Integer requestUnit; + private Integer timeToLive; + private IndexingPolicy indexingPolicy; + private boolean isVersioned; + private boolean autoCreateContainer; + + public CosmosEntityInformation(Class domainType) { + super(domainType); + + this.id = getIdField(domainType); + ReflectionUtils.makeAccessible(this.id); + + this.containerName = getContainerName(domainType); + this.partitionKeyField = getPartitionKeyField(domainType); + if (this.partitionKeyField != null) { + ReflectionUtils.makeAccessible(this.partitionKeyField); + } + + this.requestUnit = getRequestUnit(domainType); + this.timeToLive = getTimeToLive(domainType); + this.indexingPolicy = getIndexingPolicy(domainType); + this.isVersioned = getIsVersioned(domainType); + this.autoCreateContainer = getIsAutoCreateContainer(domainType); + } + + @SuppressWarnings("unchecked") + public ID getId(T entity) { + return (ID) ReflectionUtils.getField(id, entity); + } + + public Field getIdField() { + return this.id; + } + + @SuppressWarnings("unchecked") + public Class getIdType() { + return (Class) id.getType(); + } + + @Deprecated + public String getCollectionName() { + return this.containerName; + } + + public String getContainerName() { + return this.containerName; + } + + public Integer getRequestUnit() { + return this.requestUnit; + } + + public Integer getTimeToLive() { + return this.timeToLive; + } + + @NonNull + public IndexingPolicy getIndexingPolicy() { + return this.indexingPolicy; + } + + public boolean isVersioned() { + return isVersioned; + } + + public String getPartitionKeyFieldName() { + if (partitionKeyField == null) { + return null; + } else { + final PartitionKey partitionKey = partitionKeyField.getAnnotation(PartitionKey.class); + return partitionKey.value().equals("") ? partitionKeyField.getName() : partitionKey.value(); + } + } + + public String getPartitionKeyFieldValue(T entity) { + return partitionKeyField == null ? null : (String) ReflectionUtils.getField(partitionKeyField, entity); + } + + @Deprecated + public boolean isAutoCreateCollection() { + return autoCreateContainer; + } + + public boolean isAutoCreateContainer() { + return autoCreateContainer; + } + + private IndexingPolicy getIndexingPolicy(Class domainType) { + final IndexingPolicy policy = new IndexingPolicy(); + + policy.automatic(this.getIndexingPolicyAutomatic(domainType)); + policy.indexingMode(this.getIndexingPolicyMode(domainType)); + policy.setIncludedPaths(this.getIndexingPolicyIncludePaths(domainType)); + policy.excludedPaths(this.getIndexingPolicyExcludePaths(domainType)); + + return policy; + } + + private Field getIdField(Class domainType) { + final Field idField; + final List fields = FieldUtils.getFieldsListWithAnnotation(domainType, Id.class); + + if (fields.isEmpty()) { + idField = ReflectionUtils.findField(getJavaType(), Constants.ID_PROPERTY_NAME); + } else if (fields.size() == 1) { + idField = fields.get(0); + } else { + throw new IllegalArgumentException("only one field with @Id annotation!"); + } + + if (idField == null) { + throw new IllegalArgumentException("domain should contain @Id field or field named id"); + } else if (idField.getType() != String.class + && idField.getType() != Integer.class && idField.getType() != int.class) { + throw new IllegalArgumentException("type of id field must be String or Integer"); + } + + return idField; + } + + private String getContainerName(Class domainType) { + String customContainerName = domainType.getSimpleName(); + + final Document annotation = domainType.getAnnotation(Document.class); + + if (annotation != null && annotation.collection() != null && !annotation.collection().isEmpty()) { + customContainerName = resolveExpression(annotation.collection()); + } + + return customContainerName; + } + + private Field getPartitionKeyField(Class domainType) { + Field partitionKey = null; + + final List fields = FieldUtils.getFieldsListWithAnnotation(domainType, PartitionKey.class); + + if (fields.size() == 1) { + partitionKey = fields.get(0); + } else if (fields.size() > 1) { + throw new IllegalArgumentException("Azure Cosmos DB supports only one partition key, " + + "only one field with @PartitionKey annotation!"); + } + + if (partitionKey != null && partitionKey.getType() != String.class) { + throw new IllegalArgumentException("type of PartitionKey field must be String"); + } + return partitionKey; + } + + private Integer getRequestUnit(Class domainType) { + Integer ru = Integer.parseInt(Constants.DEFAULT_REQUEST_UNIT); + final Document annotation = domainType.getAnnotation(Document.class); + + if (annotation != null && annotation.ru() != null && !annotation.ru().isEmpty()) { + ru = Integer.parseInt(annotation.ru()); + } + return ru; + } + + private Integer getTimeToLive(Class domainType) { + Integer ttl = Constants.DEFAULT_TIME_TO_LIVE; + final Document annotation = domainType.getAnnotation(Document.class); + + if (annotation != null) { + ttl = annotation.timeToLive(); + } + + return ttl; + } + + + private Boolean getIndexingPolicyAutomatic(Class domainType) { + Boolean isAutomatic = Boolean.valueOf(Constants.DEFAULT_INDEXINGPOLICY_AUTOMATIC); + final DocumentIndexingPolicy annotation = domainType.getAnnotation(DocumentIndexingPolicy.class); + + if (annotation != null) { + isAutomatic = Boolean.valueOf(annotation.automatic()); + } + + return isAutomatic; + } + + private IndexingMode getIndexingPolicyMode(Class domainType) { + IndexingMode mode = Constants.DEFAULT_INDEXINGPOLICY_MODE; + final DocumentIndexingPolicy annotation = domainType.getAnnotation(DocumentIndexingPolicy.class); + + if (annotation != null) { + mode = annotation.mode(); + } + + return mode; + } + + private List getIndexingPolicyIncludePaths(Class domainType) { + final List pathArrayList = new ArrayList<>(); + final DocumentIndexingPolicy annotation = domainType.getAnnotation(DocumentIndexingPolicy.class); + + if (annotation == null || annotation.includePaths() == null || annotation.includePaths().length == 0) { + return null; // Align the default value of IndexingPolicy + } + + final String[] rawPaths = annotation.includePaths(); + + for (final String path : rawPaths) { + pathArrayList.add(new IncludedPath(path)); + } + + return pathArrayList; + } + + private List getIndexingPolicyExcludePaths(Class domainType) { + final List pathArrayList = new ArrayList<>(); + final DocumentIndexingPolicy annotation = domainType.getAnnotation(DocumentIndexingPolicy.class); + + if (annotation == null || annotation.excludePaths().length == 0) { + return null; // Align the default value of IndexingPolicy + } + + final String[] rawPaths = annotation.excludePaths(); + for (final String path : rawPaths) { + final JSONObject obj = new JSONObject(path); + pathArrayList.add(new ExcludedPath().path(obj.get("path").toString())); + } + + return pathArrayList; + } + + private boolean getIsVersioned(Class domainType) { + final Field findField = ReflectionUtils.findField(domainType, ETAG); + return findField != null + && findField.getType() == String.class + && findField.isAnnotationPresent(Version.class); + } + + private boolean getIsAutoCreateContainer(Class domainType) { + final Document annotation = domainType.getAnnotation(Document.class); + + boolean autoCreateContainer = Constants.DEFAULT_AUTO_CREATE_CONTAINER; + if (annotation != null) { + autoCreateContainer = annotation.autoCreateCollection(); + } + + return autoCreateContainer; + } + +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java new file mode 100644 index 000000000000..07ca3fe57cba --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.repository.query.CosmosQueryMethod; +import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeCosmosQuery; +import org.springframework.context.ApplicationContext; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.core.NamedQueries; +import org.springframework.data.repository.core.RepositoryInformation; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.util.Assert; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Optional; + + +public class CosmosRepositoryFactory extends RepositoryFactorySupport { + + private final ApplicationContext applicationContext; + private final CosmosOperations cosmosOperations; + + public CosmosRepositoryFactory(CosmosOperations cosmosOperations, ApplicationContext applicationContext) { + this.cosmosOperations = cosmosOperations; + this.applicationContext = applicationContext; + } + + @Override + protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { + return SimpleCosmosRepository.class; + } + + @Override + protected Object getTargetRepository(RepositoryInformation information) { + final EntityInformation entityInformation = getEntityInformation(information.getDomainType()); + return getTargetRepositoryViaReflection(information, entityInformation, this.applicationContext); + } + + @Override + public EntityInformation getEntityInformation(Class domainType) { + return new CosmosEntityInformation<>(domainType); + } + + @Override + protected Optional getQueryLookupStrategy( + QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) { + return Optional.of(new CosmosDbQueryLookupStrategy(cosmosOperations, evaluationContextProvider)); + } + + private static class CosmosDbQueryLookupStrategy implements QueryLookupStrategy { + private final CosmosOperations dbOperations; + + public CosmosDbQueryLookupStrategy( + CosmosOperations operations, QueryMethodEvaluationContextProvider provider) { + this.dbOperations = operations; + } + + @Override + public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, + ProjectionFactory factory, NamedQueries namedQueries) { + final CosmosQueryMethod queryMethod = new CosmosQueryMethod(method, metadata, factory); + + Assert.notNull(queryMethod, "queryMethod must not be null!"); + Assert.notNull(dbOperations, "dbOperations must not be null!"); + return new PartTreeCosmosQuery(queryMethod, dbOperations); + + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java new file mode 100644 index 000000000000..b1561e6cb3d2 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; + +import java.io.Serializable; + + +public class CosmosRepositoryFactoryBean, S, ID extends Serializable> + extends RepositoryFactoryBeanSupport + implements ApplicationContextAware { + + private ApplicationContext applicationContext; + private CosmosOperations operations; + private boolean mappingContextConfigured = false; + + + public CosmosRepositoryFactoryBean(Class repositoryInterface) { + super(repositoryInterface); + } + + @Autowired + public void setCosmosOperations(CosmosOperations operations) { + this.operations = operations; + } + + @Override + protected final RepositoryFactorySupport createRepositoryFactory() { + return getFactoryInstance(applicationContext); + } + + protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) { + return new CosmosRepositoryFactory(operations, applicationContext); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + protected void setMappingContext(MappingContext mappingContext) { + super.setMappingContext(mappingContext); + this.mappingContextConfigured = true; + } + + @Override + public void afterPropertiesSet() { + super.afterPropertiesSet(); + + if (!this.mappingContextConfigured) { + if (operations != null) { + setMappingContext(operations.getConverter().getMappingContext()); + } else { + setMappingContext(new CosmosMappingContext()); + } + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java new file mode 100644 index 000000000000..1904c728de76 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeReactiveCosmosQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.query.ReactiveCosmosQueryMethod; +import org.springframework.context.ApplicationContext; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.core.NamedQueries; +import org.springframework.data.repository.core.RepositoryInformation; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.ReactiveRepositoryFactorySupport; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.util.Assert; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Optional; + +public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySupport { + + private final ApplicationContext applicationContext; + private final ReactiveCosmosOperations cosmosOperations; + + public ReactiveCosmosRepositoryFactory(ReactiveCosmosOperations cosmosOperations, + ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + this.cosmosOperations = cosmosOperations; + } + + @Override + public EntityInformation getEntityInformation(Class domainType) { + return new CosmosEntityInformation<>(domainType); + } + + @Override + protected Object getTargetRepository(RepositoryInformation information) { + final EntityInformation entityInformation = + getEntityInformation(information.getDomainType()); + return getTargetRepositoryViaReflection(information, entityInformation, + this.applicationContext); + } + + @Override + protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { + return SimpleReactiveCosmosRepository.class; + } + + @Override + protected Optional getQueryLookupStrategy( + QueryLookupStrategy.Key key, + QueryMethodEvaluationContextProvider evaluationContextProvider) { + return Optional.of(new ReactiveCosmosQueryLookupStrategy(cosmosOperations, + evaluationContextProvider)); + } + + private static class ReactiveCosmosQueryLookupStrategy implements QueryLookupStrategy { + private final ReactiveCosmosOperations cosmosOperations; + + public ReactiveCosmosQueryLookupStrategy( + ReactiveCosmosOperations operations, QueryMethodEvaluationContextProvider provider) { + this.cosmosOperations = operations; + } + + @Override + public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, + ProjectionFactory factory, NamedQueries namedQueries) { + final ReactiveCosmosQueryMethod queryMethod = new ReactiveCosmosQueryMethod(method, + metadata, factory); + + Assert.notNull(queryMethod, "queryMethod must not be null!"); + Assert.notNull(cosmosOperations, "dbOperations must not be null!"); + return new PartTreeReactiveCosmosQuery(queryMethod, cosmosOperations); + + } + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java new file mode 100644 index 000000000000..f6057430ab6c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; + +import java.io.Serializable; + +public class ReactiveCosmosRepositoryFactoryBean, S, + K extends Serializable> + extends RepositoryFactoryBeanSupport + implements ApplicationContextAware { + + private ApplicationContext applicationContext; + private ReactiveCosmosOperations cosmosOperations; + private boolean mappingContextConfigured = false; + + public ReactiveCosmosRepositoryFactoryBean(Class repositoryInterface) { + super(repositoryInterface); + } + + @Autowired + public void setReactiveCosmosOperations(ReactiveCosmosOperations operations) { + this.cosmosOperations = operations; + } + + @Override + protected final RepositoryFactorySupport createRepositoryFactory() { + return getFactoryInstance(applicationContext); + } + + protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) { + return new ReactiveCosmosRepositoryFactory(cosmosOperations, applicationContext); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + protected void setMappingContext(MappingContext mappingContext) { + super.setMappingContext(mappingContext); + this.mappingContextConfigured = true; + } + + @Override + public void afterPropertiesSet() { + super.afterPropertiesSet(); + + if (!this.mappingContextConfigured) { + if (cosmosOperations != null) { + setMappingContext(cosmosOperations.getConverter().getMappingContext()); + } else { + setMappingContext(new CosmosMappingContext()); + } + } + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java new file mode 100644 index 000000000000..b87b5e5d6c46 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java @@ -0,0 +1,268 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.context.ApplicationContext; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.StreamSupport; + +public class SimpleCosmosRepository implements CosmosRepository { + + private final CosmosOperations operation; + private final CosmosEntityInformation information; + + public SimpleCosmosRepository(CosmosEntityInformation metadata, + ApplicationContext applicationContext) { + this.operation = applicationContext.getBean(CosmosOperations.class); + this.information = metadata; + + if (this.information.isAutoCreateContainer()) { + createContainerIfNotExists(); + } + } + + public SimpleCosmosRepository(CosmosEntityInformation metadata, + CosmosOperations dbOperations) { + this.operation = dbOperations; + this.information = metadata; + + if (this.information.isAutoCreateContainer()) { + createContainerIfNotExists(); + } + } + + private CosmosContainerProperties createContainerIfNotExists() { + return this.operation.createContainerIfNotExists(this.information); + } + + /** + * save entity without partition + * + * @param entity to be saved + * @param + * @return entity + */ + @Override + public S save(S entity) { + Assert.notNull(entity, "entity must not be null"); + + // save entity + if (information.isNew(entity)) { + return operation.insert(information.getContainerName(), + entity, + createKey(information.getPartitionKeyFieldValue(entity))); + } else { + return operation.upsertAndReturnEntity(information.getContainerName(), + entity, createKey(information.getPartitionKeyFieldValue(entity))); + } + } + + private PartitionKey createKey(String partitionKeyValue) { + if (StringUtils.isEmpty(partitionKeyValue)) { + return PartitionKey.None; + } + + return new PartitionKey(partitionKeyValue); + } + + /** + * batch save entities + * + * @param entities + * @param + * @return + */ + @Override + public Iterable saveAll(Iterable entities) { + Assert.notNull(entities, "Iterable entities should not be null"); + + final List savedEntities = new ArrayList<>(); + entities.forEach(entity -> { + final S savedEntity = this.save(entity); + savedEntities.add(savedEntity); + }); + + return savedEntities; + } + + /** + * find all entities from one container without configuring partition key value + * + * @return + */ + @Override + public Iterable findAll() { + return operation.findAll(information.getContainerName(), information.getJavaType()); + } + + /** + * find entities based on id list from one container without partitions + * + * @param ids + * @return + */ + @Override + public List findAllById(Iterable ids) { + Assert.notNull(ids, "Iterable ids should not be null"); + + return operation.findByIds(ids, information.getJavaType(), information.getContainerName()); + } + + /** + * find one entity per id without partitions + * + * @param id + * @return + */ + @Override + public Optional findById(ID id) { + Assert.notNull(id, "id must not be null"); + + if (id instanceof String && !StringUtils.hasText((String) id)) { + return Optional.empty(); + } + + return Optional.ofNullable(operation.findById(information.getContainerName(), id, information.getJavaType())); + } + + @Override + public Optional findById(ID id, PartitionKey partitionKey) { + Assert.notNull(id, "id must not be null"); + + if (id instanceof String && !StringUtils.hasText((String) id)) { + return Optional.empty(); + } + + return Optional.ofNullable(operation.findById(id, information.getJavaType(), partitionKey)); + } + + /** + * return count of documents in one container without partitions + * + * @return + */ + @Override + public long count() { + return operation.count(information.getContainerName()); + } + + /** + * delete one document per id without configuring partition key value + * + * @param id + */ + @Override + public void deleteById(ID id) { + Assert.notNull(id, "id to be deleted should not be null"); + + operation.deleteById(information.getContainerName(), id, null); + } + + @Override + public void deleteById(ID id, PartitionKey partitionKey) { + Assert.notNull(id, "id to be deleted should not be null"); + Assert.notNull(partitionKey, "partitionKey to be deleted should not be null"); + + operation.deleteById(information.getContainerName(), id, partitionKey); + } + + /** + * delete one document per entity + * + * @param entity + */ + @Override + public void delete(T entity) { + Assert.notNull(entity, "entity to be deleted should not be null"); + + final String partitionKeyValue = information.getPartitionKeyFieldValue(entity); + + operation.deleteById(information.getContainerName(), + information.getId(entity), + partitionKeyValue == null ? null : new PartitionKey(partitionKeyValue)); + } + + /** + * delete all the domains of a container + */ + @Override + public void deleteAll() { + operation.deleteAll(information.getContainerName(), information.getJavaType()); + } + + /** + * delete list of entities without partitions + * + * @param entities + */ + @Override + public void deleteAll(Iterable entities) { + Assert.notNull(entities, "Iterable entities should not be null"); + + StreamSupport.stream(entities.spliterator(), true).forEach(this::delete); + } + + /** + * check if an entity exists per id without partition + * + * @param primaryKey + * @return + */ + @Override + public boolean existsById(ID primaryKey) { + Assert.notNull(primaryKey, "primaryKey should not be null"); + + return findById(primaryKey).isPresent(); + } + + /** + * Returns all entities sorted by the given options. + * + * @param sort + * @return all entities sorted by the given options + */ + @Override + public Iterable findAll(@NonNull Sort sort) { + Assert.notNull(sort, "sort of findAll should not be null"); + final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort); + + return operation.find(query, information.getJavaType(), information.getContainerName()); + } + + /** + * FindQuerySpecGenerator + * Returns a Page of entities meeting the paging restriction provided in the Pageable object. + * + * @param pageable + * @return a page of entities + */ + @Override + public Page findAll(Pageable pageable) { + Assert.notNull(pageable, "pageable should not be null"); + + return operation.findAll(pageable, information.getJavaType(), information.getContainerName()); + } + + @Override + public List findAll(PartitionKey partitionKey) { + return operation.findAll(partitionKey, information.getJavaType()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java new file mode 100644 index 000000000000..3b925c197a94 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.azure.data.cosmos.CosmosContainerResponse; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository; +import org.reactivestreams.Publisher; +import org.springframework.context.ApplicationContext; +import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.Serializable; + +public class SimpleReactiveCosmosRepository implements ReactiveCosmosRepository { + + private final CosmosEntityInformation entityInformation; + private final ReactiveCosmosOperations cosmosOperations; + + public SimpleReactiveCosmosRepository(CosmosEntityInformation metadata, + ApplicationContext applicationContext) { + this.cosmosOperations = applicationContext.getBean(ReactiveCosmosOperations.class); + this.entityInformation = metadata; + + if (this.entityInformation.isAutoCreateContainer()) { + createContainerIfNotExists(); + } + } + + public SimpleReactiveCosmosRepository(CosmosEntityInformation metadata, + ReactiveCosmosOperations reactiveCosmosOperations) { + this.cosmosOperations = reactiveCosmosOperations; + this.entityInformation = metadata; + + if (this.entityInformation.isAutoCreateContainer()) { + createContainerIfNotExists(); + } + } + + private CosmosContainerResponse createContainerIfNotExists() { + return this.cosmosOperations.createContainerIfNotExists(this.entityInformation).block(); + } + + @Override + public Flux findAll(Sort sort) { + Assert.notNull(sort, "Sort must not be null!"); + + final DocumentQuery query = + new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort); + + return cosmosOperations.find(query, entityInformation.getJavaType(), + entityInformation.getContainerName()); + } + + @Override + public Flux findAll(PartitionKey partitionKey) { + return cosmosOperations.findAll(partitionKey, entityInformation.getJavaType()); + } + + @Override + public Mono save(S entity) { + + Assert.notNull(entity, "Entity must not be null!"); + + if (entityInformation.isNew(entity)) { + return cosmosOperations.insert(entityInformation.getContainerName(), + entity, + createKey(entityInformation.getPartitionKeyFieldValue(entity))); + } else { + return cosmosOperations.upsert(entityInformation.getContainerName(), + entity, createKey(entityInformation.getPartitionKeyFieldValue(entity))); + } + } + + @Override + public Flux saveAll(Iterable entities) { + + Assert.notNull(entities, "The given Iterable of entities must not be null!"); + + return Flux.fromIterable(entities).flatMap(this::save); + } + + @Override + public Flux saveAll(Publisher entityStream) { + + Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); + + return Flux.from(entityStream).flatMap(this::save); + } + + @Override + public Mono findById(K id) { + Assert.notNull(id, "The given id must not be null!"); + return cosmosOperations.findById(entityInformation.getContainerName(), id, + entityInformation.getJavaType()); + } + + @Override + public Mono findById(Publisher publisher) { + Assert.notNull(publisher, "The given id must not be null!"); + + return Mono.from(publisher).flatMap( + id -> cosmosOperations.findById(entityInformation.getContainerName(), + id, entityInformation.getJavaType())); + } + + @Override + public Mono findById(K id, PartitionKey partitionKey) { + Assert.notNull(id, "The given id must not be null!"); + return cosmosOperations.findById(id, + entityInformation.getJavaType(), partitionKey); + } + + @Override + public Mono existsById(K id) { + Assert.notNull(id, "The given id must not be null!"); + + return cosmosOperations.existsById(id, entityInformation.getJavaType(), + entityInformation.getContainerName()); + } + + @Override + public Mono existsById(Publisher publisher) { + Assert.notNull(publisher, "The given id must not be null!"); + + return Mono.from(publisher).flatMap(id -> cosmosOperations.existsById(id, + entityInformation.getJavaType(), + entityInformation.getContainerName())); + } + + @Override + public Flux findAll() { + return cosmosOperations.findAll(entityInformation.getContainerName(), + entityInformation.getJavaType()); + } + + @Override + public Flux findAllById(Iterable ids) { + Assert.notNull(ids, "Iterable ids should not be null"); + throw new UnsupportedOperationException(); + } + + @Override + public Flux findAllById(Publisher ids) { + Assert.notNull(ids, "The given Publisher of Id's must not be null!"); + throw new UnsupportedOperationException(); + } + + @Override + public Mono count() { + return cosmosOperations.count(entityInformation.getContainerName()); + } + + @Override + public Mono deleteById(K id) { + Assert.notNull(id, "The given id must not be null!"); + + return cosmosOperations.deleteById(entityInformation.getContainerName(), id, null); + } + + @Override + public Mono deleteById(Publisher publisher) { + Assert.notNull(publisher, "Id must not be null!"); + + return Mono.from(publisher).flatMap(id -> cosmosOperations.deleteById(entityInformation.getContainerName(), + id, null)).then(); + } + + @Override + public Mono deleteById(K id, PartitionKey partitionKey) { + Assert.notNull(id, "Id must not be null!"); + Assert.notNull(partitionKey, "PartitionKey must not be null!"); + + return cosmosOperations.deleteById(entityInformation.getContainerName(), id, partitionKey); + + } + + @Override + public Mono delete(@NonNull T entity) { + Assert.notNull(entity, "entity to be deleted must not be null!"); + + final Object id = entityInformation.getId(entity); + return cosmosOperations.deleteById(entityInformation.getContainerName(), + id, + createKey(entityInformation.getPartitionKeyFieldValue(entity))); + } + + @Override + public Mono deleteAll(Iterable entities) { + Assert.notNull(entities, "The given Iterable of entities must not be null!"); + + return Flux.fromIterable(entities).flatMap(this::delete).then(); + } + + @Override + public Mono deleteAll(Publisher entityStream) { + + Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); + + return Flux.from(entityStream)// + .map(entityInformation::getRequiredId)// + .flatMap(this::deleteById)// + .then(); + } + + @Override + public Mono deleteAll() { + return cosmosOperations.deleteAll(entityInformation.getContainerName(), + entityInformation.getPartitionKeyFieldName()); + } + + private PartitionKey createKey(String partitionKeyValue) { + if (StringUtils.isEmpty(partitionKeyValue)) { + return null; + } + return new PartitionKey(partitionKeyValue); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties new file mode 100644 index 000000000000..90d42083480f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties @@ -0,0 +1 @@ +project.version=@project.version@ diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000000..1884afe05dff --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactory \ No newline at end of file diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config new file mode 100644 index 000000000000..61b615fa0ef1 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config @@ -0,0 +1 @@ +telemetry.instrumentationKey=@telemetry.instrumentationKey@ \ No newline at end of file diff --git a/sdk/spring/pom.xml b/sdk/spring/pom.xml index b9e7c1e1216c..0f714b4b2faf 100644 --- a/sdk/spring/pom.xml +++ b/sdk/spring/pom.xml @@ -20,6 +20,7 @@ azure-spring-boot-starter-servicebus-jms azure-spring-boot-samples azure-spring-boot-tests + azure-spring-data-cosmosdb From 91dd74c348dba7bfe91558b3ff339f793995ba4a Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 11 Jun 2020 11:18:04 +0800 Subject: [PATCH 03/17] modify pom and dependency versions --- eng/versioning/external_dependencies.txt | 21 ++++++++++ eng/versioning/version_client.txt | 2 +- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 40 +++++++++---------- sdk/spring/ci.yml | 2 +- 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index 93839243d0a7..1838a1cf05f1 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -4,7 +4,9 @@ com.fasterxml.jackson.core:jackson-annotations;2.10.1 com.fasterxml.jackson.core:jackson-core;2.10.1 com.fasterxml.jackson.core:jackson-databind;2.10.1 com.fasterxml.jackson.dataformat:jackson-dataformat-xml;2.10.1 +com.fasterxml.jackson.datatype:jackson-datatype-jdk8;2.10.0 com.fasterxml.jackson.datatype:jackson-datatype-jsr310;2.10.1 +com.fasterxml.jackson.module:jackson-module-parameter-names;2.10.0 com.github.spotbugs:spotbugs;4.0.0-beta3 com.github.spotbugs:spotbugs-maven-plugin;3.1.12.2 com.google.code.gson:gson;2.8.5 @@ -55,11 +57,14 @@ org.asynchttpclient:async-http-client;2.10.5 org.codehaus.groovy:groovy-eclipse-batch;2.5.8-01 org.codehaus.groovy:groovy-eclipse-compiler;3.4.0-01 org.hibernate.validator:hibernate-validator;6.0.17.Final +org.javatuples:javatuples;1.2 +org.json:json;20140107 org.linguafranca.pwdb:KeePassJava2;2.1.4 org.powermock:powermock-api-mockito2;2.0.2 org.powermock:powermock-module-junit4;2.0.2 org.slf4j:slf4j-api;1.7.28 org.slf4j:slf4j-simple;1.7.25 +<<<<<<< HEAD ## Spring boot dependency versions org.springframework.boot:spring-boot-starter-actuator;2.3.0.RELEASE @@ -82,6 +87,11 @@ org.springframework.security:spring-security-oauth2-core;5.3.2.RELEASE org.springframework.security:spring-security-oauth2-jose;5.3.2.RELEASE org.springframework:spring-web;5.2.6.RELEASE org.springframework:spring-jms;5.2.6.RELEASE +org.springframework.data:spring-data-commons;2.3.0.RELEASE +org.springframework:spring-beans;5.2.6.RELEASE +org.springframework:spring-core;5.2.6.RELEASE +org.springframework:spring-expression;5.2.6.RELEASE +org.springframework:spring-tx;5.2.6.RELEASE pl.pragmatists:JUnitParams;1.1.1 ## Test dependency versions @@ -254,3 +264,14 @@ storage_com.microsoft.azure:azure-storage;8.4.0 spring_io.micrometer:micrometer-core;1.3.0 spring_io.micrometer:micrometer-registry-azure-monitor;1.3.0 spring_com.microsoft.azure:azure;1.34.0 + +#sdk\spring\spring-data-cosmosdb\pom.xml +spring_org.springframework:spring-web;5.2.6.RELEASE +spring_com.microsoft.azure:azure-cosmos;3.7.3 +spring_com.fasterxml.jackson.datatype:jackson-datatype-jsr310;2.10.0 +spring_org.mockito:mockito-core;2.8.9 +spring_org.powermock:powermock-module-junit4;1.7.1 +spring_org.powermock:powermock-api-mockito2;1.7.1 +spring_org.springframework.boot:spring-boot-starter-test;2.3.0.RELEASE +spring_io.projectreactor:reactor-test;3.3.0.RELEASE +spring_com.google.code.gson:gson;2.8.4 diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt index 39f82e3969b6..98a8f44ed8da 100644 --- a/eng/versioning/version_client.txt +++ b/eng/versioning/version_client.txt @@ -55,7 +55,7 @@ com.microsoft.azure:azure-servicebus-jms-spring-boot-starter;2.3.2;2.3.3-beta.1 com.microsoft.azure:azure-spring-boot-metrics-starter;2.3.2;2.3.3-beta.1 com.microsoft.azure:azure-spring-boot-tests;2.3.2;2.3.3-beta.1 com.microsoft.azure:azure-spring-boot-test-core;2.3.2;2.3.3-beta.1 - +com.microsoft.azure:spring-data-cosmosdb;2.3.0;2.3.1-beta.1 # Unreleased dependencies: Copy the entry from above, prepend "unreleased_" and remove the current # version. Unreleased dependencies are only valid for dependency versions. diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 2cabdd5c3aa6..c76ae61792d6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -77,7 +77,7 @@ org.springframework spring-core - ${spring.springframework.version} + ${spring.springframework.version} commons-logging @@ -89,94 +89,94 @@ org.springframework spring-web - ${spring.springframework.version} + ${spring.springframework.version} org.springframework spring-beans - ${spring.springframework.version} + ${spring.springframework.version} org.springframework spring-context - ${spring.springframework.version} + ${spring.springframework.version} org.springframework spring-tx - ${spring.springframework.version} + ${spring.springframework.version} org.springframework.data spring-data-commons - ${spring.data.version} + ${spring.data.version} org.springframework spring-expression - ${spring.springframework.version} + ${spring.springframework.version} com.microsoft.azure azure-cosmos - ${azure.cosmos.version} + ${azure.cosmos.version} com.fasterxml.jackson.module jackson-module-parameter-names - ${fasterxml.jackson.version} + ${fasterxml.jackson.version} com.fasterxml.jackson.datatype jackson-datatype-jdk8 - ${fasterxml.jackson.version} + ${fasterxml.jackson.version} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - ${fasterxml.jackson.version} + ${fasterxml.jackson.version} org.json json - 20140107 + 20140107 org.javatuples javatuples - ${java.tuples.version} + ${java.tuples.version} org.mockito mockito-core - ${mockito.core.version} + ${mockito.core.version} test org.powermock powermock-module-junit4 - ${powermock.version} + ${powermock.version} test org.powermock powermock-api-mockito2 - ${powermock.version} + ${powermock.version} test org.springframework.boot spring-boot-starter-test - ${spring.boot.starter.test.version} + ${spring.boot.starter.test.version} test @@ -189,21 +189,21 @@ io.projectreactor reactor-test - ${project.reactor.test.version} + ${project.reactor.test.version} test org.slf4j slf4j-simple - ${slf4j.version} + ${slf4j.version} test com.google.code.gson gson - ${gson.version} + ${gson.version} test diff --git a/sdk/spring/ci.yml b/sdk/spring/ci.yml index 760553812278..7ccde32252d2 100644 --- a/sdk/spring/ci.yml +++ b/sdk/spring/ci.yml @@ -83,4 +83,4 @@ extends: - name: azure-spring-boot-sample-servicebus-jms-topic groupId: com.microsoft.azure - name: azure-spring-boot-sample-storage-blob - groupId: com.microsoft.azure \ No newline at end of file + groupId: com.microsoft.azure From 976d6973640012d86d63346654d0bd1356e4b91a Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 11 Jun 2020 18:52:43 +0800 Subject: [PATCH 04/17] add tests --- eng/versioning/external_dependencies.txt | 6 + .../HowToContribute.md | 64 --- .../azure-spring-data-cosmosdb/README.md | 2 +- .../config/findbugs-exclude.xml | 13 + sdk/spring/azure-spring-data-cosmosdb/pom.xml | 210 ++++--- .../core/ReactiveCosmosTemplate.java | 1 + .../core/convert/MappingCosmosConverter.java | 9 +- .../generator/AbstractQueryGenerator.java | 2 +- .../repository/query/CosmosQueryMethod.java | 2 +- .../query/ReactiveCosmosEntityMetadata.java | 2 +- .../query/ReactiveCosmosQueryMethod.java | 2 +- .../CosmosDbFactoryTestIT.java | 71 +++ .../UserAgentTestIT.java | 39 ++ .../common/DynamicContainer.java | 16 + .../common/ExpressionResolverUnitTest.java | 49 ++ .../common/MemoizerUnitTest.java | 54 ++ .../common/PageTestUtils.java | 41 ++ .../common/PropertyLoaderUnitTest.java | 24 + .../common/ResponseDiagnosticsTestUtils.java | 42 ++ .../common/TestConstants.java | 152 +++++ .../common/TestUtils.java | 40 ++ .../config/AbstractCosmosConfigurationIT.java | 153 +++++ .../core/CosmosTemplateIT.java | 436 +++++++++++++++ .../core/CosmosTemplateIllegalTest.java | 111 ++++ .../core/CosmosTemplatePartitionIT.java | 241 ++++++++ .../core/CosmosTemplateUnitTest.java | 23 + .../core/ReactiveCosmosTemplateIT.java | 402 +++++++++++++ .../ReactiveCosmosTemplatePartitionIT.java | 204 +++++++ .../ZonedDateTimeDeserializerTest.java | 49 ++ .../MappingCosmosConverterUnitTest.java | 111 ++++ .../BasicCosmosPersistentEntityUnitTest.java | 28 + .../mapping/CosmosMappingContextUnitTest.java | 29 + .../core/query/CriteriaUnitTest.java | 66 +++ .../core/query/DocumentQueryUnitTest.java | 28 + .../domain/Address.java | 86 +++ .../domain/Contact.java | 63 +++ .../domain/Course.java | 82 +++ .../domain/Customer.java | 121 ++++ .../domain/Importance.java | 7 + .../domain/IntegerIdDomain.java | 63 +++ .../domain/Memo.java | 88 +++ .../domain/NoDBAnnotationPerson.java | 92 +++ .../domain/PageableAddress.java | 76 +++ .../domain/PageableMemo.java | 84 +++ .../domain/PageablePerson.java | 116 ++++ .../domain/PartitionPerson.java | 100 ++++ .../domain/Person.java | 116 ++++ .../domain/Project.java | 117 ++++ .../domain/Question.java | 69 +++ .../domain/Role.java | 91 +++ .../domain/SortedProject.java | 117 ++++ .../domain/SpELBeanStudent.java | 72 +++ .../domain/SpELPropertyStudent.java | 72 +++ .../domain/Student.java | 70 +++ .../domain/TimeToLiveSample.java | 23 + .../domain/inheritance/Shape.java | 42 ++ .../domain/inheritance/Square.java | 59 ++ .../performance/PerfConfiguration.java | 28 + .../performance/PerformanceCompare.java | 289 ++++++++++ .../performance/PerformanceReport.java | 124 +++++ .../performance/domain/PerfPerson.java | 61 ++ .../repository/PerfPersonRepository.java | 17 + .../performance/service/SdkService.java | 213 +++++++ .../performance/utils/Constants.java | 9 + .../performance/utils/DatabaseUtils.java | 61 ++ .../performance/utils/FunctionUtils.java | 96 ++++ .../performance/utils/PerfDataProvider.java | 41 ++ .../repository/CosmosAnnotationUnitTest.java | 111 ++++ .../SimpleCosmosRepositoryIllegalTest.java | 68 +++ .../SimpleCosmosRepositoryUnitTest.java | 103 ++++ .../repository/TestRepositoryConfig.java | 76 +++ ...ositoryConfigurationExtensionUnitTest.java | 55 ++ ...ositoryConfigurationExtensionUnitTest.java | 57 ++ .../integration/AddressRepositoryIT.java | 238 ++++++++ .../integration/ContactRepositoryIT.java | 202 +++++++ .../integration/CosmosAnnotationIT.java | 104 ++++ .../integration/CustomerRepositoryIT.java | 104 ++++ .../IntegerIdDomainRepositoryIT.java | 261 +++++++++ .../integration/MemoRepositoryIT.java | 262 +++++++++ .../PageableAddressRepositoryIT.java | 202 +++++++ .../integration/PageableMemoRepositoryIT.java | 172 ++++++ .../PageablePersonRepositoryIT.java | 127 +++++ .../integration/PersonRepositoryIT.java | 6 + .../integration/ProjectRepositoryIT.java | 526 ++++++++++++++++++ .../integration/ProjectRepositorySortIT.java | 251 +++++++++ .../integration/QuestionRepositoryIT.java | 105 ++++ .../ReactiveCourseRepositoryIT.java | 260 +++++++++ .../integration/SpELCosmosDBAnnotationIT.java | 110 ++++ .../integration/SquareRepositoryIT.java | 80 +++ .../integration/StudentRepositoryIT.java | 172 ++++++ .../repository/AddressRepository.java | 25 + .../repository/ContactRepository.java | 14 + .../repository/CustomerRepository.java | 12 + .../repository/IntegerIdDomainRepository.java | 12 + .../repository/repository/MemoRepository.java | 38 ++ .../repository/PageableAddressRepository.java | 16 + .../repository/PageableMemoRepository.java | 11 + .../repository/PageablePersonRepository.java | 11 + .../repository/PartitionPersonRepository.java | 11 + .../repository/PersonRepository.java | 11 + .../repository/ProjectRepository.java | 86 +++ .../repository/QuestionRepository.java | 9 + .../repository/ReactiveCourseRepository.java | 14 + .../repository/SortedProjectRepository.java | 22 + .../repository/SquareRepository.java | 12 + .../repository/StudentRepository.java | 35 ++ .../CosmosEntityInformationUnitTest.java | 355 ++++++++++++ .../CosmosRepositoryFactoryBeanUnitTest.java | 27 + .../CosmosRepositoryFactoryUnitTest.java | 32 ++ .../src/test/resources/application.properties | 15 + .../src/test/resources/application.yml | 4 + .../src/test/resources/logback-test.xml | 15 + 112 files changed, 9738 insertions(+), 188 deletions(-) delete mode 100644 sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md create mode 100644 sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index 1838a1cf05f1..f58e0a29460d 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -47,6 +47,7 @@ javax.annotation:javax.annotation-api;1.3.2 javax.servlet:javax.servlet-api;4.0.1 javax.validation:validation-api;2.0.1.Final net.minidev:json-smart;2.3 +org.apache.ant:ant;1.9.4 org.apache.avro:avro;1.9.2 org.apache.httpcomponents:httpclient;4.3.6 org.apache.logging.log4j:log4j-api;2.11.1 @@ -193,7 +194,9 @@ org.apache.maven.plugins:maven-source-plugin;3.0.1 org.apache.maven.plugins:maven-surefire-plugin;3.0.0-M3 org.apidesign.javadoc:codesnippet-doclet;0.53 org.codehaus.mojo:build-helper-maven-plugin;3.0.0 +org.codehaus.mojo:cobertura-maven-plugin;2.7 org.codehaus.mojo:exec-maven-plugin;1.2.1 +org.codehaus.mojo:findbugs-maven-plugin;3.0.5 org.codehaus.mojo:properties-maven-plugin;1.0.0 org.codehaus.mojo:xml-maven-plugin;1.0 org.eclipse.jetty:jetty-maven-plugin;9.3.22.v20171030 @@ -275,3 +278,6 @@ spring_org.powermock:powermock-api-mockito2;1.7.1 spring_org.springframework.boot:spring-boot-starter-test;2.3.0.RELEASE spring_io.projectreactor:reactor-test;3.3.0.RELEASE spring_com.google.code.gson:gson;2.8.4 +spring_org.apache.maven.plugins:maven-surefire-plugin;2.12.4 +spring_org.apache.maven.plugins:maven-help-plugin;3.1.0 +spring_org.apache.maven.plugins:maven-source-plugin;2.2.1 diff --git a/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md b/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md deleted file mode 100644 index ea1355c840b5..000000000000 --- a/sdk/spring/azure-spring-data-cosmosdb/HowToContribute.md +++ /dev/null @@ -1,64 +0,0 @@ -# How to Build and Contribute -This instruction is guideline for building and code contribution. - -## Prequisites -- JDK 1.8 and above -- [Maven](http://maven.apache.org/) 3.0 and above - -## Build from source -To build the project, run maven commands. - -```bash -git clone https://github.com/Microsoft/spring-data-cosmosdb.git -cd spring-data-cosmosdb -mvnw clean install -``` - -## Test -There're 3 profiles: `dev`, `integration-test-azure` and `integration-test-emulator`. Default profile is `dev`. Profile `integration-test-azure` will trigger integration test execution against Azure Cosmos DB. Profile `integration-test-emulator` will trigger integration test execution against [Azure Cosmos DB Emulator](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator), you need to follow the link to setup emulator before test execution. - -- Run unit tests -```bash -mvnw clean install -``` - -- Run integration tests - - on Azure - >**NOTE** Please note that integration test against Azure will automatically create a Azure Cosmos DB Document API in your Azure subscription, then there will be **Azure usage fee.** - - Integration tests will require a Azure Subscription. If you don't already have an Azure subscription, you can activate your [MSDN subscriber benefits](https://azure.microsoft.com/en-us/pricing/member-offers/msdn-benefits-details/) or sign up for a [free Azure account](https://azure.microsoft.com/en-us/free/). - - 1. Create a service principal by using Azure Cli or by [Azure Portal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal). - 2. After service principal ready, set environment variables CLIENT_ID, CLIENT_KEY and TENANT_ID, where value of them are service principal id, key and tenant id. - 3. Run maven command with `integration-test-azure` profile. - - ```bash - set CLIENT_ID=your-azure-service-principal-id - set CLIENT_KEY=your-azure-service-principal-key - set TENANT_ID=your-azure-subscription-tenant-id - mvnw -P integration-test-azure clean install - ``` - - on Emulator - - Setup Azure Cosmos DB Emulator by following [this instruction](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator), then run test with: - ```bash - mvnw -P integration-test-emulator install - ``` - - -- Skip tests execution -```bash -mvnw clean install -DskipTests -``` - -## Version management -Developing version naming convention is like `0.1.2-SNAPSHOT`. Release version naming convention is like `0.1.2`. - -## CI -Both [travis](https://travis-ci.org/Microsoft/spring-data-cosmosdb) and [appveyor](https://ci.appveyor.com/project/yungez/spring-data-cosmosdb) CI is enabled. - -## Contribute to code -Code contribution is welcome. To contribute to this module, please make sure below check list are checked. -- [ ] Build pass. checkstyle and findbugs is enabled by default. Please check [checkstyle.xml](config/checkstyle.xml) to learn detail checkstyle configuration. -- [ ] Documents are updated to align with code. -- [ ] Code coverage for new codes >= 65%. Code coverage check is enabled with 65% bar. diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/spring/azure-spring-data-cosmosdb/README.md index 849a8e3ed4b2..0005be53ddb6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/README.md +++ b/sdk/spring/azure-spring-data-cosmosdb/README.md @@ -324,7 +324,7 @@ To suggest a new feature or changes that could be made, file an issue the same w ## How To Contribute -Contribution is welcome. Please follow [this instruction](./HowToContribute.md) to contribute code. +Contribution is welcome. Please follow [this instruction](https://github.com/Azure/azure-sdk-for-java/blob/master/CONTRIBUTING.md) to contribute code. ## Code of Conduct diff --git a/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml b/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml new file mode 100644 index 000000000000..6a89562b9ca1 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index c76ae61792d6..d19ff42775b3 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -3,6 +3,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + com.azure + azure-client-sdk-parent + 1.7.0 + ../../parents/azure-client-sdk-parent + com.microsoft.azure spring-data-cosmosdb @@ -45,22 +51,9 @@ UTF-8 MM-dd-HH-mm-ss - 5.2.6.RELEASE - 2.3.0.RELEASE - 2.10.0 - - 2.8.9 - 1.7.1 - 2.3.0.RELEASE - 1.2 - 1.7.25 - 2.8.4 - 3.3.0.RELEASE - - 3.7.3 spring-data-cosmosdb-test testdb-${maven.build.timestamp} - true + false false false @@ -77,7 +70,7 @@ org.springframework spring-core - ${spring.springframework.version} + 5.2.6.RELEASE commons-logging @@ -89,58 +82,58 @@ org.springframework spring-web - ${spring.springframework.version} + 5.2.6.RELEASE org.springframework spring-beans - ${spring.springframework.version} + 5.2.6.RELEASE org.springframework spring-context - ${spring.springframework.version} + 5.2.6.RELEASE org.springframework spring-tx - ${spring.springframework.version} + 5.2.6.RELEASE org.springframework.data spring-data-commons - ${spring.data.version} + 2.3.0.RELEASE org.springframework spring-expression - ${spring.springframework.version} + 5.2.6.RELEASE com.microsoft.azure azure-cosmos - ${azure.cosmos.version} + 3.7.3 com.fasterxml.jackson.module jackson-module-parameter-names - ${fasterxml.jackson.version} + 2.10.0 com.fasterxml.jackson.datatype jackson-datatype-jdk8 - ${fasterxml.jackson.version} + 2.10.0 com.fasterxml.jackson.datatype jackson-datatype-jsr310 - ${fasterxml.jackson.version} + 2.10.0 org.json @@ -151,32 +144,32 @@ org.javatuples javatuples - ${java.tuples.version} + 1.2 org.mockito mockito-core - ${mockito.core.version} + 2.8.9 test org.powermock powermock-module-junit4 - ${powermock.version} + 1.7.1 test org.powermock powermock-api-mockito2 - ${powermock.version} + 1.7.1 test org.springframework.boot spring-boot-starter-test - ${spring.boot.starter.test.version} + 2.3.0.RELEASE test @@ -189,21 +182,21 @@ io.projectreactor reactor-test - ${project.reactor.test.version} + 3.3.0.RELEASE test org.slf4j slf4j-simple - ${slf4j.version} + 1.7.25 test com.google.code.gson gson - ${gson.version} + 2.8.4 test @@ -221,91 +214,58 @@ - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 - - private - false - - - com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicCosmosPersistentProperty.java - - - - - - attach-javadocs - - jar - - - ${javadoc.opts} - - - + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + + org.springframework:*:5.2.6.RELEASE + org.springframework.data:spring-data-commons:2.3.0.RELEASE + com.microsoft.azure:azure-cosmos:3.7.3 + org.javatuples:javatuples:1.2 + com.fasterxml.jackson.datatype:*:2.10.0 + org.json:json:20140107 + com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + + + + - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.17 - - - validate - validate - - ${project.basedir}/config/checkstyle.xml - UTF-8 - true - true - true - true - - - check - - - - - false - - true + org.apache.maven.plugins + maven-help-plugin + 3.1.0 + + + show-profiles + compile + + active-profiles + + + - - org.apache.maven.plugins - maven-help-plugin - 3.1.0 - - - show-profiles - compile - - active-profiles - - - - - - org.codehaus.mojo findbugs-maven-plugin - 3.0.5 + 3.0.5 Max Low @@ -318,7 +278,7 @@ org.apache.ant ant - 1.9.4 + 1.9.4 @@ -333,7 +293,7 @@ org.codehaus.mojo cobertura-maven-plugin - 2.7 + 2.7 html @@ -356,7 +316,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.19 + 2.22.0 src/test/resources/application.properties ${skip.integration.tests} @@ -371,11 +331,28 @@ - + + + + + + + + + + + + + + + + + + org.apache.maven.plugins maven-antrun-plugin - 1.8 + 1.8 setup @@ -452,6 +429,7 @@ org.apache.maven.plugins maven-surefire-plugin + 2.12.4 true @@ -459,7 +437,8 @@ org.apache.maven.plugins maven-failsafe-plugin - + 2.22.0 + PerformanceCompare.java @@ -481,6 +460,7 @@ org.apache.maven.plugins maven-failsafe-plugin + 2.22.0 diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java index 6db018dabf7a..99b207397e1a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java @@ -42,6 +42,7 @@ import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.exceptionHandler; import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.findAPIExceptionHandler; +@SuppressWarnings("unchecked") public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, ApplicationContextAware { private static final String COUNT_VALUE_KEY = "_aggregate"; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java index 4caafc2cc3ef..ef99a8abaf8d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java @@ -29,6 +29,7 @@ import static com.microsoft.azure.spring.data.cosmosdb.Constants.ISO_8601_COMPATIBLE_DATE_PATTERN; +@SuppressWarnings("unchecked") public class MappingCosmosConverter implements EntityConverter, CosmosPersistentProperty, Object, CosmosItemProperties>, @@ -100,7 +101,7 @@ public CosmosItemProperties writeCosmosItemProperties(Object sourceEntity) { throw new MappingException("no mapping metadata for entity type: " + sourceEntity.getClass().getName()); } - final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity); + final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity); final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty(); final CosmosItemProperties cosmosItemProperties; @@ -139,13 +140,13 @@ public MappingContext, CosmosPersistentPrope } - private ConvertingPropertyAccessor getPropertyAccessor(Object entity) { + private ConvertingPropertyAccessor getPropertyAccessor(Object entity) { final CosmosPersistentEntity entityInformation = mappingContext.getPersistentEntity(entity.getClass()); Assert.notNull(entityInformation, "EntityInformation should not be null."); - final PersistentPropertyAccessor accessor = entityInformation.getPropertyAccessor(entity); - return new ConvertingPropertyAccessor(accessor, conversionService); + final PersistentPropertyAccessor accessor = entityInformation.getPropertyAccessor(entity); + return new ConvertingPropertyAccessor<> (accessor, conversionService); } /** diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java index 932e94ac94e5..95b4b036d240 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java @@ -89,7 +89,7 @@ private String generateInQuery(Criteria criteria) { throw new IllegalQueryException("IN keyword requires Collection type in parameters"); } final List inRangeValues = new ArrayList<>(); - final Collection values = (Collection) criteria.getSubjectValues().get(0); + final Collection values = (Collection) criteria.getSubjectValues().get(0); values.forEach(o -> { if (o instanceof Integer || o instanceof Long) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java index 3241c0602ab6..4c6c4cfc9455 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java @@ -22,7 +22,7 @@ public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionF @SuppressWarnings("unchecked") public EntityMetadata getEntityInformation() { final Class domainType = (Class) getDomainClass(); - final CosmosEntityInformation entityInformation = + final CosmosEntityInformation entityInformation = new CosmosEntityInformation(domainType); this.metadata = new SimpleCosmosEntityMetadata(domainType, entityInformation); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java index b35a893d1234..5535427db920 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java @@ -4,7 +4,7 @@ import org.springframework.data.repository.core.EntityMetadata; -public interface ReactiveCosmosEntityMetadata extends EntityMetadata { +public interface ReactiveCosmosEntityMetadata extends EntityMetadata { @Deprecated String getCollectionName(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java index 25018802eb64..468bd6c2e744 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java @@ -22,7 +22,7 @@ public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, Pro @SuppressWarnings("unchecked") public EntityMetadata getEntityInformation() { final Class domainType = (Class) getDomainClass(); - final CosmosEntityInformation entityInformation = + final CosmosEntityInformation entityInformation = new CosmosEntityInformation(domainType); this.metadata = new SimpleReactiveCosmosEntityMetadata(domainType, entityInformation); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java new file mode 100644 index 000000000000..c897788b58f4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb; + +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_CONNECTION_STRING; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_HOST; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_KEY; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_INVALID_FAKE_CONNECTION_STRING; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.DB_NAME; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class CosmosDbFactoryTestIT { + + @Value("${cosmosdb.uri:}") + private String cosmosDbUri; + + @Value("${cosmosdb.key:}") + private String cosmosDbKey; + + @Test(expected = IllegalArgumentException.class) + public void testEmptyKey() { + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, "", DB_NAME).build(); + new CosmosDbFactory(dbConfig); + } + + @Test + public void testInvalidEndpoint() { + final CosmosDBConfig dbConfig = + CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build(); + final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); + + assertThat(factory).isNotNull(); + } + + @Test + public void testConnectWithConnectionString() { + final CosmosDBConfig dbConfig = + CosmosDBConfig.builder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build(); + final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); + + assertThat(factory).isNotNull(); + } + + @Test(expected = CosmosDBAccessException.class) + public void testInvalidConnectionString() { + CosmosDBConfig.builder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build(); + } + + @Test + public void testConnectionPolicyUserAgentKept() { + final CosmosDBConfig dbConfig = + CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build(); + final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); + factory.getCosmosClient(); + + final String uaSuffix = factory.getConfig().getConnectionPolicy().userAgentSuffix(); + assertThat(uaSuffix).contains("spring-data"); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java new file mode 100644 index 000000000000..b05d69425065 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb; + +import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.springframework.context.annotation.PropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +@Ignore("Cannot use fake uri and key with CosmosDbFactory as it tries the connection on new creation." + + "At the same time, cannot use mockito with real values, because it won't prepare PropertyLoader class for mocking") +@RunWith(PowerMockRunner.class) +@PrepareForTest(PropertyLoader.class) +@PropertySource(value = {"classpath:application.properties"}) +public class UserAgentTestIT { + + private static final String TEST_VERSION = "1.0.0-FOR-TEST"; + + @Test + public void testUserAgentSuffixAppended() { + PowerMockito.mockStatic(PropertyLoader.class); + Mockito.doReturn(TEST_VERSION).when(PropertyLoader.getProjectVersion()); + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(TestConstants.COSMOSDB_FAKE_HOST, + TestConstants.COSMOSDB_FAKE_KEY, TestConstants.DB_NAME).build(); + final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); + factory.getCosmosClient(); + assertThat(factory.getConfig().getConnectionPolicy().userAgentSuffix()).contains(TEST_VERSION); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java new file mode 100644 index 000000000000..1f635b5f3a04 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.common; + +public class DynamicContainer { + private String containerName; + + public DynamicContainer(String containerName) { + this.containerName = containerName; + } + + public String getContainerName() { + return this.containerName; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java new file mode 100644 index 000000000000..96f5177ca67f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.junit.Test; + +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * + * @author Domenico Sibilio + * + */ +public class ExpressionResolverUnitTest { + private static final String LITERAL_EXPRESSION = "literal expression"; + private static final String SPEL_EXPRESSION = "#{@environment.getProperty('dynamic.collection.name')}"; + + @Test + public void testLiteralExpressionsShouldNotBeAltered() { + assertEquals(LITERAL_EXPRESSION, ExpressionResolver.resolveExpression(LITERAL_EXPRESSION)); + } + + @Test + public void testExpressionsShouldBeResolved() { + final AnnotationConfigApplicationContext applicationContext = + new AnnotationConfigApplicationContext(TestConfiguration.class); + + assertNotNull(applicationContext.getBean(ExpressionResolver.class)); + assertEquals(TestConstants.DYNAMIC_PROPERTY_COLLECTION_NAME, + ExpressionResolver.resolveExpression(SPEL_EXPRESSION)); + } + + @Configuration + @PropertySource("application.properties") + static class TestConfiguration { + @Bean + public ExpressionResolver expressionResolver(ConfigurableBeanFactory beanFactory) { + return new ExpressionResolver((ConfigurableBeanFactory) beanFactory); + } + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java new file mode 100644 index 000000000000..6f56a0e75430 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.IntStream; + +/** + * + * @author Domenico Sibilio + * + */ +public class MemoizerUnitTest { + private static final String KEY = "key_1"; + private static final Map countMap = new HashMap<>(); + private static final Function memoizedFunction = + Memoizer.memoize(MemoizerUnitTest::incrCount); + + @Before + public void setUp() { + countMap.put(KEY, new AtomicInteger(0)); + } + + @Test + public void testMemoizedFunctionShouldBeCalledOnlyOnce() { + IntStream + .range(0, 10) + .forEach(number -> memoizedFunction.apply(KEY)); + + assertEquals(1, countMap.get(KEY).get()); + } + + @Test + public void testDifferentMemoizersShouldNotShareTheSameCache() { + IntStream + .range(0, 10) + .forEach(number -> Memoizer.memoize(MemoizerUnitTest::incrCount).apply(KEY)); + + assertEquals(10, countMap.get(KEY).get()); + } + + private static int incrCount(String key) { + return countMap.get(key).incrementAndGet(); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java new file mode 100644 index 000000000000..703465594920 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import org.json.JSONObject; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; + +public class PageTestUtils { + public static void validateLastPage(Page page, int pageSize) { + final Pageable pageable = page.getPageable(); + + assertThat(pageable).isInstanceOf(CosmosPageRequest.class); + assertTrue(continuationTokenIsNull((CosmosPageRequest) pageable)); + assertThat(pageable.getPageSize()).isEqualTo(pageSize); + } + + public static void validateNonLastPage(Page page, int pageSize) { + final Pageable pageable = page.getPageable(); + + assertThat(pageable).isInstanceOf(CosmosPageRequest.class); + assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotNull(); + assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotBlank(); + assertThat(pageable.getPageSize()).isEqualTo(pageSize); + } + + private static boolean continuationTokenIsNull(CosmosPageRequest pageRequest) { + final String tokenJson = pageRequest.getRequestContinuation(); + if (tokenJson == null) { + return true; + } + + final JSONObject jsonObject = new JSONObject(tokenJson); + + return jsonObject.isNull("compositeToken"); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java new file mode 100644 index 000000000000..e66f6d6ece4e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.junit.Assert; +import org.junit.Test; + +public class PropertyLoaderUnitTest { + + @Test + public void testGetProjectVersion() { + final String version = PropertyLoader.getProjectVersion(); + + Assert.assertNotNull(version); + Assert.assertNotEquals(version, ""); + } + + @Test + public void testGetApplicationTelemetryAllowed() { + final boolean isAllowed = PropertyLoader.isApplicationTelemetryAllowed(); + + Assert.assertFalse(isAllowed); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java new file mode 100644 index 000000000000..58049b859fb8 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.azure.data.cosmos.CosmosResponseDiagnostics; +import com.azure.data.cosmos.FeedResponseDiagnostics; +import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnostics; +import com.microsoft.azure.spring.data.cosmosdb.core.ResponseDiagnosticsProcessor; + + +public class ResponseDiagnosticsTestUtils { + + private final ResponseDiagnosticsProcessor responseDiagnosticsProcessor; + private ResponseDiagnostics diagnostics; + + public ResponseDiagnosticsTestUtils() { + responseDiagnosticsProcessor = responseDiagnostics -> { + diagnostics = responseDiagnostics; + }; + } + + public CosmosResponseDiagnostics getCosmosResponseDiagnostics() { + return diagnostics == null ? null : diagnostics.getCosmosResponseDiagnostics(); + } + + public FeedResponseDiagnostics getFeedResponseDiagnostics() { + return diagnostics == null ? null : diagnostics.getFeedResponseDiagnostics(); + } + + public ResponseDiagnostics.CosmosResponseStatistics getCosmosResponseStatistics() { + return diagnostics == null ? null : diagnostics.getCosmosResponseStatistics(); + } + + public ResponseDiagnosticsProcessor getResponseDiagnosticsProcessor() { + return responseDiagnosticsProcessor; + } + + public ResponseDiagnostics getDiagnostics() { + return diagnostics; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java new file mode 100644 index 000000000000..5a31b42160b6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java @@ -0,0 +1,152 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import com.azure.data.cosmos.IndexingMode; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; + +import java.util.Arrays; +import java.util.List; + +public class TestConstants { + private static final int SUFFIX_LENGTH = 1; + + private static final Address ADDRESS_1 = new Address("201107", "Zixing Road", "Shanghai"); + private static final Address ADDRESS_2 = new Address("200000", "Xuhui", "Shanghai"); + public static final List HOBBIES = Arrays.asList("photography", "fishing"); + public static final List UPDATED_HOBBIES = Arrays.asList("updatedPhotography", "updatedFishing"); + public static final List
ADDRESSES = Arrays.asList(ADDRESS_1, ADDRESS_2); + + public static final int DEFAULT_TIME_TO_LIVE = -1; + public static final String DEFAULT_COLLECTION_NAME = "Person"; + public static final int DEFAULT_REQUEST_UNIT = 4000; + public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true; + public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT; + public static final String[] DEFAULT_EXCLUDEDPATHS = {}; + public static final String[] DEFAULT_INCLUDEDPATHS = { + "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}" + + "]}", + }; + + public static final String ROLE_COLLECTION_NAME = "RoleCollectionName"; + public static final int REQUEST_UNIT = 4000; + public static final int TIME_TO_LIVE = 5; + public static final boolean INDEXINGPOLICY_AUTOMATIC = false; + public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.LAZY; + public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Point\"}" + + "]}"; + public static final String INCLUDEDPATH_1 = "{\"path\":\"/cache/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":3}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}," + + "{\"kind\":\"Spatial\",\"dataType\":\"LineString\"}" + + "]}"; + public static final String INCLUDEDPATH_2 = "{\"path\":\"/entities/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":4}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":4}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Polygon\"}" + + "]}"; + public static final String[] INCLUDEDPATHS = { + INCLUDEDPATH_0, + INCLUDEDPATH_1, + INCLUDEDPATH_2, + }; + public static final String EXCLUDEDPATH_0 = "{\"path\":\"/excluded/*\"}"; + public static final String EXCLUDEDPATH_1 = "{\"path\":\"/props/*\"}"; + public static final String[] EXCLUDEDPATHS = { + EXCLUDEDPATH_0, + EXCLUDEDPATH_1, + }; + + public static final String ORDER_BY_STRING_PATH = "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1}," + + "]}"; + + public static final String STARTSWITH_INCLUDEDPATH = + "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":3}" + + "]}"; + + public static final String[] PERSON_INCLUDEDPATHS = { + STARTSWITH_INCLUDEDPATH + }; + + public static final String DB_NAME = "testdb"; + public static final String FIRST_NAME = "first_name_li"; + public static final String LAST_NAME = "last_name_p"; + public static final String ID_1 = "id-1"; + public static final String ID_2 = "id-2"; + public static final String ID_3 = "id-3"; + public static final String ID_4 = "id-4"; + public static final String NEW_FIRST_NAME = "new_first_name"; + public static final String NEW_LAST_NAME = "new_last_name"; + public static final String UPDATED_FIRST_NAME = "updated_first_name"; + public static final String UPDATED_LAST_NAME = "updated_last_name"; + public static final String LEVEL = "B"; + public static final String ROLE_NAME = "Developer"; + public static final String NOT_EXIST_ID = "non_exist_id"; + + public static final String DATE_STRING = "8/8/2017"; + public static final String DATE_BEFORE_STRING = "8/1/2017"; + public static final String DATE_AFTER_STRING = "8/13/2017"; + public static final String DATE_FUTURE_STRING_1 = "9/13/2017"; + public static final String DATE_FUTURE_STRING_2 = "9/14/2017"; + public static final String DATE_FORMAT = "dd/MM/yyyy"; + public static final String DATE_TIMEZONE_STRING = "1/1/2000 00:00 GMT"; + public static final String DATE_TIMEZONE_FORMAT = "dd/MM/yyyy HH:mm ZZZ"; + public static final long MILLI_SECONDS = 946684800000L; + + public static final String POSTAL_CODE = "98052"; + public static final String POSTAL_CODE_0 = "00000"; + public static final String POSTAL_CODE_1 = "11111"; + public static final String CITY = "testCity"; + public static final String CITY_0 = "testCityZero"; + public static final String CITY_1 = "testCityOne"; + public static final String UPDATED_CITY = "updatedCityOne"; + public static final String STREET = "testStreet"; + public static final String STREET_0 = "testStreetZero"; + public static final String STREET_1 = "testStreetOne"; + public static final String STREET_2 = "testStreetTwo"; + public static final String NEW_STREET = "newTestStreet"; + public static final String UPDATED_STREET = "updatedTestStreet"; + public static final String MESSAGE = "test pojo with date"; + public static final String NEW_MESSAGE = "new test message"; + + public static final String CRITERIA_KEY = "CriteriaTestKey"; + public static final String CRITERIA_FAKE_KEY = "CriteriaFakeKey"; + public static final String CRITERIA_OBJECT = "CriteriaTestObject"; + + public static final String COSMOSDB_FAKE_HOST = "https://fakeuri"; + public static final String COSMOSDB_FAKE_KEY = "fakekey"; + public static final String COSMOSDB_FAKE_CONNECTION_STRING = + "AccountEndpoint=https://fakeuri/;AccountKey=fakekey;"; + public static final String COSMOSDB_INVALID_FAKE_CONNECTION_STRING = "invalid connection string"; + + public static final String PROPERTY_ID = "id"; + public static final String PROPERTY_FIRST_NAME = "firstName"; + public static final String PROPERTY_LAST_NAME = "lastName"; + public static final String PROPERTY_HOBBIES = "hobbies"; + public static final String PROPERTY_SHIPPING_ADDRESSES = "shippingAddresses"; + + public static final String PROPERTY_CITY = "city"; + public static final String PROPERTY_STREET = "street"; + + public static final String PROPERTY_MESSAGE = "message"; + public static final String PROPERTY_DATE = "date"; + + public static final int PAGE_SIZE_1 = 1; + public static final int PAGE_SIZE_2 = 2; + public static final int PAGE_SIZE_3 = 3; + + public static final String DYNAMIC_PROPERTY_COLLECTION_NAME = "spel-property-collection"; + public static final String DYNAMIC_BEAN_COLLECTION_NAME = "spel-bean-collection"; + + private TestConstants() { + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java new file mode 100644 index 000000000000..16549a191757 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.common; + +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class TestUtils { + public static List toList(Iterable iterable) { + if (iterable != null) { + final List list = new ArrayList<>(); + iterable.forEach(list::add); + return list; + } + return null; + } + + public static void testIndexingPolicyPathsEquals(List policyPaths, + String [] pathsExpected) { + if (policyPaths == null) { + throw new IllegalStateException("policyPaths should not be null"); + } else if (pathsExpected == null) { + throw new IllegalStateException("pathsExpected should not be null"); + } + + final Iterator pathIterator = policyPaths.iterator(); + + Assert.isTrue(pathsExpected.length == policyPaths.size(), "unmatched size of policy paths"); + + for (final String path: pathsExpected) { + Assert.isTrue(pathIterator.hasNext(), "policy path iterator should have next"); + final T includedPath = pathIterator.next(); + Assert.isTrue(includedPath.toString().equals(path), "unmatched policy path"); + } + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java new file mode 100644 index 000000000000..a3fdd33fc4ef --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.config; + +import com.azure.data.cosmos.ConsistencyLevel; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.internal.RequestOptions; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.Constants; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import org.assertj.core.api.Assertions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mock; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.util.StringUtils; + +import static org.junit.Assert.assertNotNull; + +public class AbstractCosmosConfigurationIT { + private static final String OBJECTMAPPER_BEAN_NAME = Constants.OBJECTMAPPER_BEAN_NAME; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void containsExpressionResolver() { + final AbstractApplicationContext context = new AnnotationConfigApplicationContext( + TestCosmosConfiguration.class); + + assertNotNull(context.getBean(ExpressionResolver.class)); + } + + @Test + public void containsCosmosDbFactory() { + final AbstractApplicationContext context = new AnnotationConfigApplicationContext( + TestCosmosConfiguration.class); + + Assertions.assertThat(context.getBean(CosmosDbFactory.class)).isNotNull(); + } + + @Test(expected = NoSuchBeanDefinitionException.class) + public void defaultObjectMapperBeanNotExists() { + final AbstractApplicationContext context = new AnnotationConfigApplicationContext( + TestCosmosConfiguration.class); + + context.getBean(ObjectMapper.class); + } + + @Test + public void objectMapperIsConfigurable() { + final AbstractApplicationContext context = new AnnotationConfigApplicationContext( + ObjectMapperConfiguration.class); + + Assertions.assertThat(context.getBean(ObjectMapper.class)).isNotNull(); + Assertions.assertThat(context.getBean(OBJECTMAPPER_BEAN_NAME)).isNotNull(); + } + + @Test + public void testRequestOptionsConfigurable() { + final AbstractApplicationContext context = new AnnotationConfigApplicationContext( + RequestOptionsConfiguration.class); + final CosmosDbFactory factory = context.getBean(CosmosDbFactory.class); + + Assertions.assertThat(factory).isNotNull(); + + final RequestOptions options = factory.getConfig().getRequestOptions(); + + Assertions.assertThat(options).isNotNull(); + Assertions.assertThat(options.getConsistencyLevel()).isEqualTo(ConsistencyLevel.CONSISTENT_PREFIX); + Assertions.assertThat(options.isScriptLoggingEnabled()).isTrue(); + } + + @Configuration + @PropertySource(value = {"classpath:application.properties"}) + static class TestCosmosConfiguration extends AbstractCosmosConfiguration { + + @Value("${cosmosdb.uri:}") + private String cosmosDbUri; + + @Value("${cosmosdb.key:}") + private String cosmosDbKey; + + @Value("${cosmosdb.database:}") + private String database; + + @Mock + private CosmosClient mockClient; + + @Bean + public CosmosDBConfig getConfig() { + final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName).build(); + } + + @Override + public CosmosClient cosmosClient(CosmosDBConfig config) { + return mockClient; + } + } + + @Configuration + static class ObjectMapperConfiguration extends TestCosmosConfiguration { + @Bean(name = OBJECTMAPPER_BEAN_NAME) + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + } + + @Configuration + @PropertySource(value = {"classpath:application.properties"}) + static class RequestOptionsConfiguration extends AbstractCosmosConfiguration { + + @Value("${cosmosdb.uri:}") + private String cosmosDbUri; + + @Value("${cosmosdb.key:}") + private String cosmosDbKey; + + @Value("${cosmosdb.database:}") + private String database; + + private RequestOptions getRequestOptions() { + final RequestOptions options = new RequestOptions(); + + options.setConsistencyLevel(ConsistencyLevel.CONSISTENT_PREFIX); + options.setScriptLoggingEnabled(true); + + return options; + } + + @Bean + public CosmosDBConfig getConfig() { + final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; + final RequestOptions options = getRequestOptions(); + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName) + .requestOptions(options) + .build(); + } + + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java new file mode 100644 index 000000000000..fee2dfc684d0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java @@ -0,0 +1,436 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.ResponseDiagnosticsTestUtils; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateNonLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ADDRESSES; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.FIRST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.HOBBIES; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ID_1; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ID_2; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ID_3; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.LAST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.NEW_FIRST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.NEW_LAST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.NOT_EXIST_ID; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PAGE_SIZE_1; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PAGE_SIZE_2; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PAGE_SIZE_3; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.UPDATED_FIRST_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class CosmosTemplateIT { + private static final Person TEST_PERSON = new Person(ID_1, FIRST_NAME, LAST_NAME, HOBBIES, + ADDRESSES); + + private static final Person TEST_PERSON_2 = new Person(ID_2, + NEW_FIRST_NAME, + NEW_LAST_NAME, HOBBIES, ADDRESSES); + + private static final Person TEST_PERSON_3 = new Person(ID_3, + NEW_FIRST_NAME, + NEW_LAST_NAME, HOBBIES, ADDRESSES); + + private static final String PRECONDITION_IS_NOT_MET = "is not met"; + + private static final String WRONG_ETAG = "WRONG_ETAG"; + + private static CosmosTemplate cosmosTemplate; + private static CosmosEntityInformation personInfo; + private static String containerName; + private static boolean initialized; + + private Person insertedPerson; + + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CosmosDBConfig dbConfig; + @Autowired + private ResponseDiagnosticsTestUtils responseDiagnosticsTestUtils; + + @Before + public void setUp() throws ClassNotFoundException { + if (!initialized) { + final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); + + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + personInfo = new CosmosEntityInformation<>(Person.class); + containerName = personInfo.getContainerName(); + + mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final MappingCosmosConverter cosmosConverter = new MappingCosmosConverter(mappingContext, + null); + cosmosTemplate = new CosmosTemplate(cosmosDbFactory, cosmosConverter, dbConfig.getDatabase()); + cosmosTemplate.createContainerIfNotExists(personInfo); + initialized = true; + } + + insertedPerson = cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null); + } + + @After + public void cleanup() { + cosmosTemplate.deleteAll(Person.class.getSimpleName(), Person.class); + } + + @AfterClass + public static void afterClassCleanup() { + cosmosTemplate.deleteContainer(personInfo.getContainerName()); + } + + @Test(expected = CosmosDBAccessException.class) + public void testInsertDuplicateId() { + cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + } + + @Test + public void testFindAll() { + final List result = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class); + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0)).isEqualTo(TEST_PERSON); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindById() { + final Person result = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), Person.class); + assertEquals(result, TEST_PERSON); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + + final Person nullResult = cosmosTemplate.findById(Person.class.getSimpleName(), + NOT_EXIST_ID, Person.class); + assertThat(nullResult).isNull(); + } + + @Test + public void testFindByMultiIds() { + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + cosmosTemplate.insert(TEST_PERSON_3, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3))); + + final List ids = Lists.newArrayList(ID_1, ID_2, ID_3); + final List result = cosmosTemplate.findByIds(ids, Person.class, containerName); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + + final List expected = Lists.newArrayList(TEST_PERSON, TEST_PERSON_2, TEST_PERSON_3); + assertThat(result.size()).isEqualTo(expected.size()); + assertThat(result).containsAll(expected); + } + + @Test + public void testUpsertNewDocument() { + // Delete first as was inserted in setup + cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(), + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + + final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString(); + final Person newPerson = new Person(TEST_PERSON.getId(), firstName, + NEW_FIRST_NAME, null, null); + + final Person person = cosmosTemplate.upsertAndReturnEntity(Person.class.getSimpleName(), + newPerson, + new PartitionKey(personInfo.getPartitionKeyFieldValue(newPerson))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + assertEquals(person.getFirstName(), firstName); + } + + @Test + public void testUpdateWithReturnEntity() { + final Person updated = new Person(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses()); + updated.set_etag(insertedPerson.get_etag()); + + final Person updatedPerson = cosmosTemplate.upsertAndReturnEntity(Person.class.getSimpleName(), + updated, null); + + final Person findPersonById = cosmosTemplate.findById(Person.class.getSimpleName(), + updatedPerson.getId(), Person.class); + + assertEquals(updatedPerson, updated); + assertThat(updatedPerson.get_etag()).isEqualTo(findPersonById.get_etag()); + } + + @Test + public void testUpdate() { + final Person updated = new Person(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses()); + updated.set_etag(insertedPerson.get_etag()); + + final Person person = cosmosTemplate.upsertAndReturnEntity(Person.class.getSimpleName(), + updated, null); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + assertEquals(person, updated); + } + + @Test + public void testOptimisticLockWhenUpdatingWithWrongEtag() { + final Person updated = new Person(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses()); + updated.set_etag(WRONG_ETAG); + + try { + cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null); + } catch (CosmosDBAccessException e) { + assertThat(e.getCosmosClientException()).isNotNull(); + final Throwable cosmosClientException = e.getCosmosClientException(); + assertThat(cosmosClientException).isInstanceOf(CosmosClientException.class); + assertThat(cosmosClientException.getMessage()).contains(PRECONDITION_IS_NOT_MET); + + final Person unmodifiedPerson = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), Person.class); + assertThat(unmodifiedPerson.getFirstName()).isEqualTo(insertedPerson.getFirstName()); + return; + } + + fail(); + } + + @Test + public void testDeleteById() { + cosmosTemplate.insert(TEST_PERSON_2, null); + assertThat(cosmosTemplate.findAll(Person.class).size()).isEqualTo(2); + + cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(), + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + final List result = cosmosTemplate.findAll(Person.class); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(result.size()).isEqualTo(1); + assertEquals(result.get(0), TEST_PERSON_2); + } + + @Test + public void testCountByContainer() { + final long prevCount = cosmosTemplate.count(containerName); + assertThat(prevCount).isEqualTo(1); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + + final long newCount = cosmosTemplate.count(containerName); + assertThat(newCount).isEqualTo(2); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testCountByQuery() { + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Collections.singletonList(TEST_PERSON_2.getFirstName())); + final DocumentQuery query = new DocumentQuery(criteria); + + final long count = cosmosTemplate.count(query, Person.class, containerName); + assertThat(count).isEqualTo(1); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindAllPageableMultiPages() { + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null); + final Page page1 = cosmosTemplate.findAll(pageRequest, Person.class, containerName); + + assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1); + validateNonLastPage(page1, PAGE_SIZE_1); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + + final Page page2 = cosmosTemplate.findAll(page1.getPageable(), Person.class, + containerName); + assertThat(page2.getContent().size()).isEqualTo(1); + validateLastPage(page2, PAGE_SIZE_1); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testPaginationQuery() { + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Collections.singletonList(FIRST_NAME)); + final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null); + final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest); + + final Page page = cosmosTemplate.paginationQuery(query, Person.class, containerName); + assertThat(page.getContent().size()).isEqualTo(1); + validateLastPage(page, page.getContent().size()); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindAllWithPageableAndSort() { + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + cosmosTemplate.insert(TEST_PERSON_3, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3))); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + + final Sort sort = Sort.by(Sort.Direction.DESC, "firstName"); + final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_3, null, sort); + + final Page page = cosmosTemplate.findAll(pageRequest, Person.class, containerName); + assertThat(page.getContent().size()).isEqualTo(3); + validateLastPage(page, PAGE_SIZE_3); + + final List result = page.getContent(); + assertThat(result.get(0).getFirstName()).isEqualTo(NEW_FIRST_NAME); + assertThat(result.get(1).getFirstName()).isEqualTo(NEW_FIRST_NAME); + assertThat(result.get(2).getFirstName()).isEqualTo(FIRST_NAME); + + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + + } + + @Test + public void testFindAllWithTwoPagesAndVerifySortOrder() { + final Person testPerson4 = new Person("id_4", "barney", NEW_LAST_NAME, HOBBIES, ADDRESSES); + final Person testPerson5 = new Person("id_5", "fred", NEW_LAST_NAME, HOBBIES, ADDRESSES); + + cosmosTemplate.insert(TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2))); + cosmosTemplate.insert(TEST_PERSON_3, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3))); + cosmosTemplate.insert(testPerson4, + new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson4))); + cosmosTemplate.insert(testPerson5, + new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson5))); + + final Sort sort = Sort.by(Sort.Direction.ASC, "firstName"); + final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_3, null, sort); + + final Page firstPage = cosmosTemplate.findAll(pageRequest, Person.class, + containerName); + + assertThat(firstPage.getContent().size()).isEqualTo(3); + validateNonLastPage(firstPage, firstPage.getContent().size()); + + final List firstPageResults = firstPage.getContent(); + assertThat(firstPageResults.get(0).getFirstName()).isEqualTo(testPerson4.getFirstName()); + assertThat(firstPageResults.get(1).getFirstName()).isEqualTo(FIRST_NAME); + assertThat(firstPageResults.get(2).getFirstName()).isEqualTo(testPerson5.getFirstName()); + + final Page secondPage = cosmosTemplate.findAll(firstPage.getPageable(), Person.class, + containerName); + + assertThat(secondPage.getContent().size()).isEqualTo(2); + validateLastPage(secondPage, secondPage.getContent().size()); + + final List secondPageResults = secondPage.getContent(); + assertThat(secondPageResults.get(0).getFirstName()).isEqualTo(NEW_FIRST_NAME); + assertThat(secondPageResults.get(1).getFirstName()).isEqualTo(NEW_FIRST_NAME); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java new file mode 100644 index 000000000000..d75736206211 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import org.apache.commons.lang3.StringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.util.Assert; + +import static com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType.IS_EQUAL; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; + +@RunWith(MockitoJUnitRunner.class) +public class CosmosTemplateIllegalTest { + private static final String NULL_STR = null; + private static final String DUMMY_COLL = "dummy"; + private static final String DUMMY_ID = "ID_1"; + private static final PartitionKey DUMMY_KEY = new PartitionKey("dummy"); + private static final String EMPTY_STR = StringUtils.EMPTY; + private static final String WHITESPACES_STR = " "; + private static final String CHECK_FAILURE_MSG = "Illegal argument is not checked"; + + @Mock(answer = Answers.CALLS_REAL_METHODS) + private CosmosTemplate dbTemplate; + private Class dbTemplateClass; + + @Before + public void setUp() { + dbTemplateClass = dbTemplate.getClass(); + } + + @Test + public void deleteIllegalShouldFail() throws NoSuchMethodException { + final Method method = dbTemplateClass.getMethod("delete", DocumentQuery.class, Class.class, String.class); + final Criteria criteria = Criteria.getInstance(IS_EQUAL, "faker", Arrays.asList("faker-value")); + final DocumentQuery query = new DocumentQuery(criteria); + + checkIllegalArgument(method, null, Person.class, DUMMY_COLL); + checkIllegalArgument(method, query, null, DUMMY_COLL); + checkIllegalArgument(method, query, Person.class, null); + } + + @Test + public void deleteIllegalContainerShouldFail() throws NoSuchMethodException { + final Method method = dbTemplateClass.getDeclaredMethod("deleteAll", String.class, Class.class); + + checkIllegalArgument(method, NULL_STR, Person.class); + checkIllegalArgument(method, EMPTY_STR, Person.class); + checkIllegalArgument(method, WHITESPACES_STR, Person.class); + } + + @Test + public void deleteByIdIllegalArgsShouldFail() throws NoSuchMethodException { + final Method method = dbTemplateClass.getDeclaredMethod("deleteById", String.class, Object.class, + PartitionKey.class); + + // Test argument containerName + checkIllegalArgument(method, null, DUMMY_ID, DUMMY_KEY); + checkIllegalArgument(method, EMPTY_STR, DUMMY_ID, DUMMY_KEY); + checkIllegalArgument(method, WHITESPACES_STR, DUMMY_ID, DUMMY_KEY); + + // Test argument id + checkIllegalArgument(method, DUMMY_COLL, null, DUMMY_KEY); + checkIllegalArgument(method, DUMMY_COLL, EMPTY_STR, DUMMY_KEY); + checkIllegalArgument(method, DUMMY_COLL, WHITESPACES_STR, DUMMY_KEY); + } + + @Test + public void findByIdIllegalArgsShouldFail() throws NoSuchMethodException { + final Method method = dbTemplateClass.getDeclaredMethod("findById", Object.class, Class.class); + + checkIllegalArgument(method, DUMMY_ID, null); + } + + @Test + public void findByCollIdIllegalArgsShouldFail() throws NoSuchMethodException { + final Method method = dbTemplateClass.getDeclaredMethod("findById", String.class, + Object.class, Class.class); + + checkIllegalArgument(method, DUMMY_COLL, null, Person.class); + checkIllegalArgument(method, DUMMY_COLL, EMPTY_STR, Person.class); + checkIllegalArgument(method, DUMMY_COLL, WHITESPACES_STR, Person.class); + } + + /** + * Check IllegalArgumentException is thrown for illegal parameters + * @param method + * @param args Method invocation parameters + */ + private void checkIllegalArgument(Method method, Object... args) { + try { + method.invoke(dbTemplate, args); + } catch (IllegalAccessException | InvocationTargetException e) { + Assert.isTrue(e.getCause() instanceof IllegalArgumentException, CHECK_FAILURE_MSG); + return; // Test passed + } + + throw new IllegalStateException(CHECK_FAILURE_MSG, null); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java new file mode 100644 index 000000000000..28a765c8446b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java @@ -0,0 +1,241 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateNonLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.*; +import static com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType.IS_EQUAL; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class CosmosTemplatePartitionIT { + private static final PartitionPerson TEST_PERSON = new PartitionPerson(ID_1, FIRST_NAME, LAST_NAME, + HOBBIES, ADDRESSES); + + private static final PartitionPerson TEST_PERSON_2 = new PartitionPerson(ID_2, NEW_FIRST_NAME, + TEST_PERSON.getLastName(), HOBBIES, ADDRESSES); + + private static CosmosTemplate cosmosTemplate; + private static String containerName; + private static CosmosEntityInformation personInfo; + private static boolean initialized; + + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CosmosDBConfig dbConfig; + + @Before + public void setUp() throws ClassNotFoundException { + if (!initialized) { + final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + + personInfo = new CosmosEntityInformation<>(PartitionPerson.class); + mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext, null); + + cosmosTemplate = new CosmosTemplate(cosmosDbFactory, dbConverter, dbConfig.getDatabase()); + containerName = personInfo.getContainerName(); + + cosmosTemplate.createContainerIfNotExists(personInfo); + initialized = true; + } + + cosmosTemplate.insert(PartitionPerson.class.getSimpleName(), TEST_PERSON, + new PartitionKey(TEST_PERSON.getLastName())); + } + + @After + public void cleanup() { + cosmosTemplate.deleteAll(personInfo.getContainerName(), PartitionPerson.class); + } + + @AfterClass + public static void afterClassCleanup() { + cosmosTemplate.deleteContainer(personInfo.getContainerName()); + } + + @Test + public void testFindWithPartition() { + Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, Arrays.asList(LAST_NAME)); + DocumentQuery query = new DocumentQuery(criteria); + List result = cosmosTemplate.find(query, PartitionPerson.class, + PartitionPerson.class.getSimpleName()); + + assertThat(result.size()).isEqualTo(1); + assertEquals(TEST_PERSON, result.get(0)); + + criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(ID_1)); + query = new DocumentQuery(criteria); + result = cosmosTemplate.find(query, PartitionPerson.class, PartitionPerson.class.getSimpleName()); + + assertThat(result.size()).isEqualTo(1); + assertEquals(TEST_PERSON, result.get(0)); + } + + + @Test + public void testFindByIdWithPartition() { + final PartitionPerson partitionPersonById = cosmosTemplate.findById(TEST_PERSON.getId(), + PartitionPerson.class, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + + assertEquals(TEST_PERSON, partitionPersonById); + } + + @Test + public void testFindByNonExistIdWithPartition() { + final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(NOT_EXIST_ID)); + final DocumentQuery query = new DocumentQuery(criteria); + + final List result = cosmosTemplate.find(query, PartitionPerson.class, + PartitionPerson.class.getSimpleName()); + assertThat(result.size()).isEqualTo(0); + } + + @Test + public void testUpsertNewDocumentPartition() { + final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString(); + final PartitionPerson newPerson = new PartitionPerson(TEST_PERSON.getId(), + firstName, NEW_LAST_NAME, + null, null); + + final String partitionKeyValue = newPerson.getLastName(); + final PartitionPerson partitionPerson = + cosmosTemplate.upsertAndReturnEntity(PartitionPerson.class.getSimpleName(), newPerson + , new PartitionKey(partitionKeyValue)); + + final List result = cosmosTemplate.findAll(PartitionPerson.class); + + assertThat(result.size()).isEqualTo(2); + assertThat(partitionPerson.getFirstName()).isEqualTo(firstName); + } + + @Test + public void testUpdatePartition() { + final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses()); + final PartitionPerson partitionPerson = + cosmosTemplate.upsertAndReturnEntity(PartitionPerson.class.getSimpleName(), updated, + new PartitionKey(updated.getLastName())); + + assertEquals(partitionPerson, updated); + } + + @Test + public void testDeleteByIdPartition() { + // insert new document with same partition key + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())); + + final List inserted = cosmosTemplate.findAll(PartitionPerson.class); + assertThat(inserted.size()).isEqualTo(2); + assertThat(inserted.get(0).getLastName()).isEqualTo(TEST_PERSON.getLastName()); + assertThat(inserted.get(1).getLastName()).isEqualTo(TEST_PERSON.getLastName()); + + cosmosTemplate.deleteById(PartitionPerson.class.getSimpleName(), + TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName())); + + final List result = cosmosTemplate.findAll(PartitionPerson.class); + assertThat(result.size()).isEqualTo(1); + assertEquals(result.get(0), TEST_PERSON_2); + } + + @Test + public void testCountForPartitionedCollection() { + final long prevCount = cosmosTemplate.count(containerName); + assertThat(prevCount).isEqualTo(1); + + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())); + + final long newCount = cosmosTemplate.count(containerName); + assertThat(newCount).isEqualTo(2); + } + + @Test + public void testCountForPartitionedCollectionByQuery() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())); + + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Arrays.asList(TEST_PERSON_2.getFirstName())); + final DocumentQuery query = new DocumentQuery(criteria); + + final long count = cosmosTemplate.count(query, PartitionPerson.class, containerName); + assertThat(count).isEqualTo(1); + } + + @Test + public void testNonExistFieldValue() { + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Arrays.asList("non-exist-first-name")); + final DocumentQuery query = new DocumentQuery(criteria); + + final long count = cosmosTemplate.count(query, PartitionPerson.class, containerName); + assertThat(count).isEqualTo(0); + } + + @Test + public void testPartitionedFindAllPageableMultiPages() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())); + + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null); + final Page page1 = cosmosTemplate.findAll(pageRequest, PartitionPerson.class, containerName); + + assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1); + validateNonLastPage(page1, PAGE_SIZE_1); + + final Page page2 = cosmosTemplate.findAll(page1.getPageable(), + PartitionPerson.class, containerName); + assertThat(page2.getContent().size()).isEqualTo(1); + validateLastPage(page2, PAGE_SIZE_1); + } + + @Test + public void testPartitionedPaginationQuery() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())); + + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Arrays.asList(FIRST_NAME)); + final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null); + final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest); + + final Page page = cosmosTemplate.paginationQuery(query, PartitionPerson.class, containerName); + assertThat(page.getContent().size()).isEqualTo(1); + validateLastPage(page, page.getContent().size()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java new file mode 100644 index 000000000000..09e796d184ec --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CosmosTemplateUnitTest { + + @Test(expected = IllegalArgumentException.class) + public void rejectNullDbFactory() { + final CosmosDBConfig dbConfig = CosmosDBConfig.builder("", "", TestConstants.DB_NAME).build(); + final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); + + new CosmosTemplate(cosmosDbFactory, null, TestConstants.DB_NAME); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java new file mode 100644 index 000000000000..0dc32b6026d0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java @@ -0,0 +1,402 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.CosmosKeyCredential; +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.ResponseDiagnosticsTestUtils; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import io.reactivex.subscribers.TestSubscriber; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.UPDATED_FIRST_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.fail; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ReactiveCosmosTemplateIT { + private static final Person TEST_PERSON = new Person(TestConstants.ID_1, + TestConstants.FIRST_NAME, + TestConstants.LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES); + + private static final Person TEST_PERSON_2 = new Person(TestConstants.ID_2, + TestConstants.NEW_FIRST_NAME, + TestConstants.NEW_LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES); + + private static final Person TEST_PERSON_3 = new Person(TestConstants.ID_3, + TestConstants.NEW_FIRST_NAME, + TestConstants.NEW_LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES); + + private static final Person TEST_PERSON_4 = new Person(TestConstants.ID_4, + TestConstants.NEW_FIRST_NAME, + TestConstants.NEW_LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES); + + private static final String PRECONDITION_IS_NOT_MET = "is not met"; + private static final String WRONG_ETAG = "WRONG_ETAG"; + + @Value("${cosmosdb.secondaryKey}") + private String cosmosDbSecondaryKey; + + private static ReactiveCosmosTemplate cosmosTemplate; + private static String containerName; + private static CosmosEntityInformation personInfo; + private static CosmosKeyCredential cosmosKeyCredential; + + private static boolean initialized; + + private Person insertedPerson; + + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CosmosDBConfig dbConfig; + @Autowired + private ResponseDiagnosticsTestUtils responseDiagnosticsTestUtils; + + @Before + public void setUp() throws ClassNotFoundException { + if (!initialized) { + cosmosKeyCredential = new CosmosKeyCredential(dbConfig.getKey()); + final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); + + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + personInfo = new CosmosEntityInformation<>(Person.class); + containerName = personInfo.getContainerName(); + + mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final MappingCosmosConverter dbConverter = + new MappingCosmosConverter(mappingContext, null); + cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, dbConfig.getDatabase()); + cosmosTemplate.createContainerIfNotExists(personInfo).block().container(); + initialized = true; + } + + insertedPerson = cosmosTemplate.insert(TEST_PERSON, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))).block(); + } + + @After + public void cleanup() { + // Reset master key + cosmosKeyCredential.key(dbConfig.getKey()); + cosmosTemplate.deleteAll(Person.class.getSimpleName(), + personInfo.getPartitionKeyFieldName()).block(); + } + + @AfterClass + public static void afterClassCleanup() { + cosmosTemplate.deleteContainer(personInfo.getContainerName()); + } + + @Test + public void testInsertDuplicateId() { + final Mono insertMono = cosmosTemplate.insert(TEST_PERSON, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + final TestSubscriber testSubscriber = new TestSubscriber(); + insertMono.subscribe(testSubscriber); + testSubscriber.awaitTerminalEvent(); + testSubscriber.assertNotComplete(); + testSubscriber.assertTerminated(); + assertThat(testSubscriber.errors()).hasSize(1); + assertThat(((List) testSubscriber.getEvents().get(1)).get(0)) + .isInstanceOf(CosmosDBAccessException.class); + } + + @Test + public void testFindByID() { + final Mono findById = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), + Person.class); + StepVerifier.create(findById) + .consumeNextWith(actual -> Assert.assertEquals(actual, TEST_PERSON)) + .verifyComplete(); + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindByIDBySecondaryKey() { + cosmosKeyCredential.key(cosmosDbSecondaryKey); + final Mono findById = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), + Person.class); + StepVerifier.create(findById).consumeNextWith(actual -> { + Assert.assertThat(actual.getFirstName(), is(equalTo(TEST_PERSON.getFirstName()))); + Assert.assertThat(actual.getLastName(), is(equalTo(TEST_PERSON.getLastName()))); + }).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindAll() { + final Flux flux = cosmosTemplate.findAll(Person.class.getSimpleName(), + Person.class); + StepVerifier.create(flux).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testFindByIdWithContainerName() { + StepVerifier.create(cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), Person.class)) + .consumeNextWith(actual -> Assert.assertEquals(actual, TEST_PERSON)) + .verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + } + + @Test + public void testInsert() { + StepVerifier.create(cosmosTemplate.insert(TEST_PERSON_3, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)))) + .expectNext(TEST_PERSON_3).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testInsertBySecondaryKey() { + cosmosKeyCredential.key(cosmosDbSecondaryKey); + StepVerifier.create(cosmosTemplate.insert(TEST_PERSON_3, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)))) + .expectNext(TEST_PERSON_3).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testInsertWithContainerName() { + StepVerifier.create(cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON_2, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)))) + .expectNext(TEST_PERSON_2).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testUpsert() { + final Person p = TEST_PERSON_2; + p.set_etag(insertedPerson.get_etag()); + final ArrayList hobbies = new ArrayList<>(p.getHobbies()); + hobbies.add("more code"); + p.setHobbies(hobbies); + final Mono upsert = cosmosTemplate.upsert(p, + new PartitionKey(personInfo.getPartitionKeyFieldValue(p))); + StepVerifier.create(upsert).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testOptimisticLockWhenUpdatingWithWrongEtag() { + final Person updated = new Person(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses()); + updated.set_etag(WRONG_ETAG); + + try { + cosmosTemplate.upsert(updated, new PartitionKey(personInfo.getPartitionKeyFieldValue(updated))).block(); + } catch (CosmosDBAccessException cosmosDbAccessException) { + assertThat(cosmosDbAccessException.getCosmosClientException()).isNotNull(); + final Throwable cosmosClientException = cosmosDbAccessException.getCosmosClientException(); + assertThat(cosmosClientException).isInstanceOf(CosmosClientException.class); + assertThat(cosmosClientException.getMessage()).contains(PRECONDITION_IS_NOT_MET); + + final Mono unmodifiedPerson = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), Person.class); + StepVerifier.create(unmodifiedPerson).expectNextMatches(person -> + person.getFirstName().equals(insertedPerson.getFirstName())).verifyComplete(); + return; + } + fail(); + } + + @Test + public void testUpsertBySecondaryKey() { + cosmosKeyCredential.key(cosmosDbSecondaryKey); + final Person p = TEST_PERSON_2; + final ArrayList hobbies = new ArrayList<>(p.getHobbies()); + hobbies.add("more code"); + p.setHobbies(hobbies); + final Mono upsert = cosmosTemplate.upsert(p, + new PartitionKey(personInfo.getPartitionKeyFieldValue(p))); + StepVerifier.create(upsert).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testUpsertWithContainerName() { + final Person p = TEST_PERSON_2; + final ArrayList hobbies = new ArrayList<>(p.getHobbies()); + hobbies.add("more code"); + p.setHobbies(hobbies); + final Mono upsert = cosmosTemplate.upsert(Person.class.getSimpleName(), p, + new PartitionKey(personInfo.getPartitionKeyFieldValue(p))); + StepVerifier.create(upsert).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + } + + @Test + public void testDeleteById() { + cosmosTemplate.insert(TEST_PERSON_4, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))).block(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + + Flux flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class); + StepVerifier.create(flux).expectNextCount(2).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + + final Mono voidMono = cosmosTemplate.deleteById(Person.class.getSimpleName(), + TEST_PERSON_4.getId(), + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))); + StepVerifier.create(voidMono).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNotNull(); + + flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class); + StepVerifier.create(flux).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + } + + @Test + public void testDeleteByIdBySecondaryKey() { + cosmosKeyCredential.key(cosmosDbSecondaryKey); + cosmosTemplate.insert(TEST_PERSON_4, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))).block(); + Flux flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class); + StepVerifier.create(flux).expectNextCount(2).verifyComplete(); + final Mono voidMono = cosmosTemplate.deleteById(Person.class.getSimpleName(), + TEST_PERSON_4.getId(), + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))); + StepVerifier.create(voidMono).verifyComplete(); + flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class); + StepVerifier.create(flux).expectNextCount(1).verifyComplete(); + } + + @Test + public void testFind() { + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Arrays.asList(TEST_PERSON.getFirstName())); + final DocumentQuery query = new DocumentQuery(criteria); + final Flux personFlux = cosmosTemplate.find(query, Person.class, + Person.class.getSimpleName()); + StepVerifier.create(personFlux).expectNextCount(1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + } + + @Test + public void testExists() { + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName", + Arrays.asList(TEST_PERSON.getFirstName())); + final DocumentQuery query = new DocumentQuery(criteria); + final Mono exists = cosmosTemplate.exists(query, Person.class, containerName); + StepVerifier.create(exists).expectNext(true).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + } + + @Test + public void testCount() { + final Mono count = cosmosTemplate.count(containerName); + StepVerifier.create(count).expectNext((long) 1).verifyComplete(); + + assertThat(responseDiagnosticsTestUtils.getFeedResponseDiagnostics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics()).isNotNull(); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseStatistics().getRequestCharge()).isGreaterThan(0); + assertThat(responseDiagnosticsTestUtils.getCosmosResponseDiagnostics()).isNull(); + } + + @Test + public void testCountBySecondaryKey() { + cosmosKeyCredential.key(cosmosDbSecondaryKey); + final Mono count = cosmosTemplate.count(containerName); + StepVerifier.create(count).expectNext((long) 1).verifyComplete(); + } + + @Test + public void testInvalidSecondaryKey() { + cosmosKeyCredential.key("Invalid secondary key"); + final Mono findById = cosmosTemplate.findById(Person.class.getSimpleName(), + TEST_PERSON.getId(), + Person.class); + StepVerifier.create(findById).expectError(IllegalArgumentException.class); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java new file mode 100644 index 000000000000..fce527da71b0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core; + +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.Arrays; +import java.util.UUID; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ADDRESSES; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.FIRST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.HOBBIES; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ID_1; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ID_2; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.LAST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.NEW_FIRST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.NEW_LAST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PROPERTY_LAST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.UPDATED_FIRST_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType.IS_EQUAL; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ReactiveCosmosTemplatePartitionIT { + private static final PartitionPerson TEST_PERSON = new PartitionPerson(ID_1, FIRST_NAME, LAST_NAME, + HOBBIES, ADDRESSES); + + private static final PartitionPerson TEST_PERSON_2 = new PartitionPerson(ID_2, NEW_FIRST_NAME, + TEST_PERSON.getLastName(), HOBBIES, ADDRESSES); + + private static ReactiveCosmosTemplate cosmosTemplate; + private static String containerName; + private static CosmosEntityInformation personInfo; + + private static boolean initialized; + + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CosmosDBConfig dbConfig; + + @Before + public void setUp() throws ClassNotFoundException { + if (!initialized) { + final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); + + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + personInfo = + new CosmosEntityInformation<>(PartitionPerson.class); + containerName = personInfo.getContainerName(); + + mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext, + null); + cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, dbConfig.getDatabase()); + cosmosTemplate.createContainerIfNotExists(personInfo).block(); + + initialized = true; + } + cosmosTemplate.insert(TEST_PERSON).block(); + } + + @After + public void cleanup() { + cosmosTemplate.deleteAll(PartitionPerson.class.getSimpleName(), + personInfo.getPartitionKeyFieldName()).block(); + } + + @AfterClass + public static void afterClassCleanup() { + cosmosTemplate.deleteContainer(personInfo.getContainerName()); + } + + @Test + public void testFindWithPartition() { + final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, + Arrays.asList(LAST_NAME)); + final DocumentQuery query = new DocumentQuery(criteria); + final Flux partitionPersonFlux = cosmosTemplate.find(query, + PartitionPerson.class, + PartitionPerson.class.getSimpleName()); + StepVerifier.create(partitionPersonFlux).consumeNextWith(actual -> { + Assert.assertThat(actual.getFirstName(), is(equalTo(TEST_PERSON.getFirstName()))); + Assert.assertThat(actual.getLastName(), is(equalTo(TEST_PERSON.getLastName()))); + }).verifyComplete(); + } + + + @Test + public void testFindByIdWithPartition() { + final Mono partitionPersonMono = cosmosTemplate.findById(TEST_PERSON.getId(), + PartitionPerson.class, + new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); + StepVerifier.create(partitionPersonMono).consumeNextWith(actual -> { + Assert.assertThat(actual.getFirstName(), is(equalTo(TEST_PERSON.getFirstName()))); + Assert.assertThat(actual.getLastName(), is(equalTo(TEST_PERSON.getLastName()))); + }).verifyComplete(); + } + + // @Test + // public void testFindByNonExistIdWithPartition() { + // + // } + + @Test + public void testUpsertNewDocumentPartition() { + final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString(); + final PartitionPerson newPerson = new PartitionPerson(UUID.randomUUID().toString(), + firstName, NEW_LAST_NAME, + null, null); + final String partitionKeyValue = newPerson.getLastName(); + final Mono upsert = cosmosTemplate.upsert(newPerson, + new PartitionKey(partitionKeyValue)); + StepVerifier.create(upsert).expectNextCount(1).verifyComplete(); + } + + @Test + public void testUpdateWithPartition() { + final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME, + TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), + TEST_PERSON.getShippingAddresses()); + cosmosTemplate.upsert(updated, new PartitionKey(updated.getLastName())).block(); + + final PartitionPerson person = cosmosTemplate + .findAll(PartitionPerson.class.getSimpleName(), PartitionPerson.class) + .toStream() + .filter(p -> TEST_PERSON.getId().equals(p.getId())) + .findFirst().get(); + assertTrue(person.equals(updated)); + } + + @Test + public void testDeleteByIdPartition() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block(); + StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)).expectNextCount(2).verifyComplete(); + + cosmosTemplate.deleteById(PartitionPerson.class.getSimpleName(), + TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName())).block(); + StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)) + .expectNext(TEST_PERSON_2) + .verifyComplete(); + } + + @Test + public void testDeleteAll() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block(); + StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)).expectNextCount(2).verifyComplete(); + final CosmosEntityInformation personInfo = + new CosmosEntityInformation<>(PartitionPerson.class); + cosmosTemplate.deleteAll(containerName, personInfo.getPartitionKeyFieldName()).block(); + StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)) + .expectNextCount(0) + .verifyComplete(); + } + + @Test + public void testCountForPartitionedCollection() { + StepVerifier.create(cosmosTemplate.count(containerName)) + .expectNext((long) 1).verifyComplete(); + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block(); + StepVerifier.create(cosmosTemplate.count(containerName)) + .expectNext((long) 2).verifyComplete(); + } + + @Test + public void testCountForPartitionedCollectionByQuery() { + cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block(); + final Criteria criteria = Criteria.getInstance(IS_EQUAL, "firstName", + Arrays.asList(TEST_PERSON_2.getFirstName())); + final DocumentQuery query = new DocumentQuery(criteria); + StepVerifier.create(cosmosTemplate.count(query, containerName)) + .expectNext((long) 1).verifyComplete(); + + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java new file mode 100644 index 000000000000..dc7622c948a4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.convert; + +import org.junit.Test; + +import java.io.IOException; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME; +import static org.assertj.core.api.Java6Assertions.assertThat; + + +public class ZonedDateTimeDeserializerTest { + private static final ZonedDateTime ZONED_DATE_TIME + = ZonedDateTime.of(2018, 10, 8, 15, 6, 7, 992000000, + ZoneId.of("UTC")); + private static final String OFFSET_DATE_TIME_WRAPPER_JSON = "{ \"zonedDateTime\": \"" + + ZONED_DATE_TIME.format(ISO_OFFSET_DATE_TIME) + "\" }"; + private static final String ZONED_DATE_TIME_WRAPPER_JSON = "{ \"zonedDateTime\": \"" + + ZONED_DATE_TIME.format(ISO_OFFSET_DATE_TIME) + "\" }"; + + @Test + public void deserializeZonedDateTime() throws IOException { + final ZonedDateTimeWrapper wrapper = ObjectMapperFactory.getObjectMapper() + .readValue(ZONED_DATE_TIME_WRAPPER_JSON, ZonedDateTimeWrapper.class); + assertThat(wrapper.getZonedDateTime()).isEqualTo(ZONED_DATE_TIME); + } + + @Test + public void deserializeOffsetDateTime() throws IOException { + final ZonedDateTimeWrapper wrapper = ObjectMapperFactory.getObjectMapper() + .readValue(OFFSET_DATE_TIME_WRAPPER_JSON, ZonedDateTimeWrapper.class); + assertThat(wrapper.getZonedDateTime()).isEqualTo(ZONED_DATE_TIME); + } + + static final class ZonedDateTimeWrapper { + ZonedDateTime zonedDateTime; + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java new file mode 100644 index 000000000000..c0d3c93947ae --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.converter; + +import com.azure.data.cosmos.CosmosItemProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.domain.Memo; +import com.microsoft.azure.spring.data.cosmosdb.domain.Importance; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.context.ApplicationContext; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(MockitoJUnitRunner.class) +public class MappingCosmosConverterUnitTest { + private static final SimpleDateFormat DATE = new SimpleDateFormat(TestConstants.DATE_FORMAT); + private static final SimpleDateFormat TIMEZONE_DATE = new SimpleDateFormat(TestConstants.DATE_TIMEZONE_FORMAT); + + private MappingCosmosConverter mappingCosmosConverter; + + @Mock + ApplicationContext applicationContext; + + @Before + public void setUp() { + final CosmosMappingContext mappingContext = new CosmosMappingContext(); + final ObjectMapper objectMapper = new ObjectMapper(); + + mappingContext.setApplicationContext(applicationContext); + mappingContext.afterPropertiesSet(); + mappingContext.getPersistentEntity(Address.class); + + mappingCosmosConverter = new MappingCosmosConverter(mappingContext, objectMapper); + } + + @Test + public void covertAddressToDocumentCorrectly() { + final Address testAddress = new Address(TestConstants.POSTAL_CODE, TestConstants.CITY, TestConstants.STREET); + final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(testAddress); + + assertThat(cosmosItemProperties.id()).isEqualTo(testAddress.getPostalCode()); + assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_CITY)).isEqualTo(testAddress.getCity()); + assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_STREET)).isEqualTo(testAddress.getStreet()); + } + + @Test + public void convertDocumentToAddressCorrectly() { + final JSONObject jsonObject = new JSONObject(); + jsonObject.put(TestConstants.PROPERTY_CITY, TestConstants.CITY); + jsonObject.put(TestConstants.PROPERTY_STREET, TestConstants.STREET); + + final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString()); + cosmosItemProperties.id(TestConstants.POSTAL_CODE); + + final Address address = mappingCosmosConverter.read(Address.class, cosmosItemProperties); + + assertThat(address.getPostalCode()).isEqualTo(TestConstants.POSTAL_CODE); + assertThat(address.getCity()).isEqualTo(TestConstants.CITY); + assertThat(address.getStreet()).isEqualTo(TestConstants.STREET); + } + + @Test + public void canWritePojoWithDateToDocument() throws ParseException { + final Memo memo = new Memo(TestConstants.ID_1, TestConstants.MESSAGE, DATE.parse(TestConstants.DATE_STRING), + Importance.NORMAL); + final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(memo); + + assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId()); + assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(memo.getMessage()); + assertThat(cosmosItemProperties.getLong(TestConstants.PROPERTY_DATE)).isEqualTo(memo.getDate().getTime()); + } + + @Test + public void canReadPojoWithDateFromDocument() throws ParseException { + final JSONObject jsonObject = new JSONObject(); + jsonObject.put(TestConstants.PROPERTY_MESSAGE, TestConstants.MESSAGE); + + final long date = DATE.parse(TestConstants.DATE_STRING).getTime(); + jsonObject.put(TestConstants.PROPERTY_DATE, date); + + final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString()); + cosmosItemProperties.id(TestConstants.ID_1); + + final Memo memo = mappingCosmosConverter.read(Memo.class, cosmosItemProperties); + assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId()); + assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(TestConstants.MESSAGE); + assertThat(cosmosItemProperties.getLong(TestConstants.PROPERTY_DATE)).isEqualTo(date); + } + + @Test + public void convertDateValueToMilliSeconds() throws ParseException { + final Date date = TIMEZONE_DATE.parse(TestConstants.DATE_TIMEZONE_STRING); + final long time = (Long) MappingCosmosConverter.toCosmosDbValue(date); + + assertThat(time).isEqualTo(TestConstants.MILLI_SECONDS); + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java new file mode 100644 index 000000000000..e86cf45b4e9c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import org.junit.Test; +import org.springframework.data.util.ClassTypeInformation; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BasicCosmosPersistentEntityUnitTest { + + @Test + public void testGetCollection() { + final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( + ClassTypeInformation.from(Person.class)); + assertThat(entity.getContainer()).isEqualTo(""); + } + + @Test + public void testGetLanguage() { + final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( + ClassTypeInformation.from(Person.class)); + assertThat(entity.getLanguage()).isEqualTo(""); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java new file mode 100644 index 000000000000..db6fd8cbed87 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; + +import org.junit.Test; +import org.mockito.Mock; +import org.springframework.context.ApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CosmosMappingContextUnitTest { + + @Mock + ApplicationContext context; + + @Test + public void mappingContextWithImplicitIdProperty() { + final CosmosMappingContext context = new CosmosMappingContext(); + final BasicCosmosPersistentEntity entity = context.getPersistentEntity(ClassWithId.class); + + assertThat(entity).isNotNull(); + } + + class ClassWithId { + String field; + String id; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java new file mode 100644 index 000000000000..7a56dc01436b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator; +import com.microsoft.azure.spring.data.cosmosdb.exception.IllegalQueryException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.CRITERIA_KEY; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.CRITERIA_OBJECT; + +public class CriteriaUnitTest { + + @Test + public void testUnaryCriteria() { + final List values = Arrays.asList(CRITERIA_OBJECT); + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, CRITERIA_KEY, values); + + Assert.assertTrue(criteria.getSubCriteria().isEmpty()); + Assert.assertEquals(values, criteria.getSubjectValues()); + Assert.assertEquals(CriteriaType.IS_EQUAL, criteria.getType()); + Assert.assertEquals(CRITERIA_KEY, criteria.getSubject()); + Assert.assertTrue(CriteriaType.isBinary(criteria.getType())); + } + + @Test + public void testBinaryCriteria() { + final List values = Arrays.asList(CRITERIA_OBJECT); + final Criteria leftCriteria = Criteria.getInstance(CriteriaType.IS_EQUAL, CRITERIA_KEY, values); + final Criteria rightCriteria = Criteria.getInstance(CriteriaType.IS_EQUAL, CRITERIA_OBJECT, values); + final Criteria criteria = Criteria.getInstance(CriteriaType.AND, leftCriteria, rightCriteria); + + Assert.assertNotNull(criteria.getSubCriteria()); + Assert.assertNull(criteria.getSubjectValues()); + Assert.assertNull(criteria.getSubject()); + Assert.assertEquals(criteria.getType(), CriteriaType.AND); + Assert.assertTrue(CriteriaType.isClosed(criteria.getType())); + + Assert.assertEquals(2, criteria.getSubCriteria().size()); + Assert.assertEquals(leftCriteria, criteria.getSubCriteria().get(0)); + Assert.assertEquals(rightCriteria, criteria.getSubCriteria().get(1)); + } + + @Test(expected = IllegalQueryException.class) + public void testInvalidInKeywordParameter() { + final List values = Collections.singletonList(CRITERIA_OBJECT); + final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values); + final DocumentQuery query = new DocumentQuery(criteria); + + new FindQuerySpecGenerator().generateCosmos(query); + } + + @Test(expected = IllegalQueryException.class) + public void testInvalidInKeywordType() { + final List values = Collections.singletonList(new IllegalQueryException("")); + final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values); + final DocumentQuery query = new DocumentQuery(criteria); + + new FindQuerySpecGenerator().generateCosmos(query); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java new file mode 100644 index 000000000000..0f65f3635d0f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.core.query; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.Arrays; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.CRITERIA_KEY; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.CRITERIA_OBJECT; + +public class DocumentQueryUnitTest { + + @Test + public void testDocumentQueryCreate() { + final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, CRITERIA_KEY, + Arrays.asList(CRITERIA_OBJECT)); + + final DocumentQuery query = new DocumentQuery(criteria); + + Assert.assertEquals(criteria, query.getCriteria()); + Assert.assertEquals(Sort.unsorted(), query.getSort()); + Assert.assertEquals(Pageable.unpaged(), query.getPageable()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java new file mode 100644 index 000000000000..7fbda44c4bb8 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.beans.ConstructorProperties; +import java.util.Objects; + +@Document() +public class Address { + @Id + String postalCode; + String street; + @PartitionKey + String city; + + public String getPostalCode() { + return postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Address address = (Address) o; + return Objects.equals(postalCode, address.postalCode) && + Objects.equals(street, address.street) && + Objects.equals(city, address.city); + } + + @Override + public int hashCode() { + return Objects.hash(postalCode, street, city); + } + + @Override + public String toString() { + return "Address{" + + "postalCode='" + + postalCode + + '\'' + + ", street='" + + street + + '\'' + + ", city='" + + city + + '\'' + + '}'; + } + + public Address(String postalCode, String street, String city) { + this.postalCode = postalCode; + this.street = street; + this.city = city; + } + + public Address() { + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java new file mode 100644 index 000000000000..73fab9000764 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document() +public class Contact { + @Id + private String logicId; + + private String title; + + public Contact(String logicId, String title) { + this.logicId = logicId; + this.title = title; + } + + public String getLogicId() { + return logicId; + } + + public void setLogicId(String logicId) { + this.logicId = logicId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Contact contact = (Contact) o; + return Objects.equals(logicId, contact.logicId) && + Objects.equals(title, contact.title); + } + + @Override + public int hashCode() { + return Objects.hash(logicId, title); + } + + @Override + public String toString() { + return "Contact{" + + "logicId='" + + logicId + + '\'' + + ", title='" + + title + + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java new file mode 100644 index 000000000000..c0a70b24e80b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document +public class Course { + + @Id + private String courseId; + private String name; + @PartitionKey + private String department; + + public Course(String courseId, String name, String department) { + this.courseId = courseId; + this.name = name; + this.department = department; + } + + public Course() { + } + + public String getCourseId() { + return courseId; + } + + public void setCourseId(String courseId) { + this.courseId = courseId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Course course = (Course) o; + return courseId.equals(course.courseId) && + name.equals(course.name) && + department.equals(course.department); + } + + @Override + public int hashCode() { + return Objects.hash(courseId, name, department); + } + + @Override + public String toString() { + return "Course{" + + "courseId='" + + courseId + + '\'' + + ", name='" + + name + + '\'' + + ", department='" + + department + + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java new file mode 100644 index 000000000000..738e2022acc8 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +public class Customer { + + @Id + private String id; + + private Long level; + + private User user; + + public Customer(String id, Long level, User user) { + this.id = id; + this.level = level; + this.user = user; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getLevel() { + return level; + } + + public void setLevel(Long level) { + this.level = level; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Customer customer = (Customer) o; + return Objects.equals(id, customer.id) && + Objects.equals(level, customer.level) && + Objects.equals(user, customer.user); + } + + @Override + public int hashCode() { + return Objects.hash(id, level, user); + } + + @Override + public String toString() { + return "Customer{" + + "id='" + id + '\'' + + ", level=" + level + + ", user=" + user + + '}'; + } + + public static class User { + + private String name; + + private Long age; + + public User(String name, Long age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getAge() { + return age; + } + + public void setAge(Long age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(name, user.name) && + Objects.equals(age, user.age); + } + + @Override + public int hashCode() { + return Objects.hash(name, age); + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java new file mode 100644 index 000000000000..0362ff9c4a43 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +public enum Importance { + HIGH, LOW, NORMAL; +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java new file mode 100644 index 000000000000..b817b7427849 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document +public class IntegerIdDomain { + + @Id + private Integer number; + + private String name; + + public IntegerIdDomain(Integer number, String name) { + this.number = number; + this.name = name; + } + + public IntegerIdDomain() { + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IntegerIdDomain that = (IntegerIdDomain) o; + return Objects.equals(number, that.number) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(number, name); + } + + @Override + public String toString() { + return "IntegerIdDomain{" + + "number=" + number + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java new file mode 100644 index 000000000000..91a3dc273645 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; + +import java.util.Date; +import java.util.Objects; + +/** + * For testing date and enum purpose + */ +@Document() +public class Memo { + private String id; + private String message; + private Date date; + private Importance importance; + + public Memo(String id, String message, Date date, Importance importance) { + this.id = id; + this.message = message; + this.date = date; + this.importance = importance; + } + + public Memo() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Importance getImportance() { + return importance; + } + + public void setImportance(Importance importance) { + this.importance = importance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Memo memo = (Memo) o; + return Objects.equals(id, memo.id) && + Objects.equals(message, memo.message) && + Objects.equals(date, memo.date) && + importance == memo.importance; + } + + @Override + public int hashCode() { + return Objects.hash(id, message, date, importance); + } + + @Override + public String toString() { + return "Memo{" + + "id='" + id + '\'' + + ", message='" + message + '\'' + + ", date=" + date + + ", importance=" + importance + + '}'; + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java new file mode 100644 index 000000000000..f3d43f782f62 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + + +import java.util.List; +import java.util.Objects; + +public class NoDBAnnotationPerson { + private String id; + private String firstName; + private String lastName; + private List hobbies; + private List
shippingAddresses; + + public NoDBAnnotationPerson(String id, String firstName, String lastName, List hobbies, List
shippingAddresses) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.hobbies = hobbies; + this.shippingAddresses = shippingAddresses; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public List getHobbies() { + return hobbies; + } + + public void setHobbies(List hobbies) { + this.hobbies = hobbies; + } + + public List
getShippingAddresses() { + return shippingAddresses; + } + + public void setShippingAddresses(List
shippingAddresses) { + this.shippingAddresses = shippingAddresses; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NoDBAnnotationPerson that = (NoDBAnnotationPerson) o; + return Objects.equals(id, that.id) && + Objects.equals(firstName, that.firstName) && + Objects.equals(lastName, that.lastName) && + Objects.equals(hobbies, that.hobbies) && + Objects.equals(shippingAddresses, that.shippingAddresses); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName, hobbies, shippingAddresses); + } + + @Override + public String toString() { + return "NoDBAnnotationPerson{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", hobbies=" + hobbies + + ", shippingAddresses=" + shippingAddresses + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java new file mode 100644 index 000000000000..f8bf72d0bd15 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document() +public class PageableAddress { + @Id + private String postalCode; + private String street; + @PartitionKey + private String city; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final PageableAddress address = (PageableAddress) o; + return Objects.equals(postalCode, address.postalCode) && + Objects.equals(street, address.street) && + Objects.equals(city, address.city); + } + + @Override + public int hashCode() { + return Objects.hash(postalCode, street, city); + } + + public PageableAddress(String postalCode, String street, String city) { + this.postalCode = postalCode; + this.street = street; + this.city = city; + } + + public String getPostalCode() { + return postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + @Override + public String toString() { + return "PageableAddress{" + + "postalCode='" + postalCode + '\'' + + ", street='" + street + '\'' + + ", city='" + city + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java new file mode 100644 index 000000000000..c0c2fb1afe54 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; + +import java.util.Date; +import java.util.Objects; + +/** + * For testing date and enum purpose + */ +@Document() +public class PageableMemo { + private String id; + private String message; + private Date date; + private Importance importance; + + public PageableMemo(String id, String message, Date date, Importance importance) { + this.id = id; + this.message = message; + this.date = date; + this.importance = importance; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Importance getImportance() { + return importance; + } + + public void setImportance(Importance importance) { + this.importance = importance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PageableMemo that = (PageableMemo) o; + return Objects.equals(id, that.id) && + Objects.equals(message, that.message) && + Objects.equals(date, that.date) && + importance == that.importance; + } + + @Override + public int hashCode() { + return Objects.hash(id, message, date, importance); + } + + @Override + public String toString() { + return "PageableMemo{" + + "id='" + id + '\'' + + ", message='" + message + '\'' + + ", date=" + date + + ", importance=" + importance + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java new file mode 100644 index 000000000000..b1c3a109e2f0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Version; + +import java.util.List; +import java.util.Objects; + +@Document() +@DocumentIndexingPolicy(includePaths = TestConstants.ORDER_BY_STRING_PATH) +public class PageablePerson { + private String id; + private String firstName; + + @PartitionKey + private String lastName; + private List hobbies; + private List
shippingAddresses; + @Version + private String _etag; + + public PageablePerson(String id, String firstName, String lastName, + List hobbies, List
shippingAddresses) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.hobbies = hobbies; + this.shippingAddresses = shippingAddresses; + } + + public PageablePerson() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public List getHobbies() { + return hobbies; + } + + public void setHobbies(List hobbies) { + this.hobbies = hobbies; + } + + public List
getShippingAddresses() { + return shippingAddresses; + } + + public void setShippingAddresses(List
shippingAddresses) { + this.shippingAddresses = shippingAddresses; + } + + public String get_etag() { + return _etag; + } + + public void set_etag(String _etag) { + this._etag = _etag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PageablePerson that = (PageablePerson) o; + return Objects.equals(id, that.id) && + Objects.equals(firstName, that.firstName) && + Objects.equals(lastName, that.lastName) && + Objects.equals(hobbies, that.hobbies) && + Objects.equals(shippingAddresses, that.shippingAddresses); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName, hobbies, shippingAddresses); + } + + @Override + public String toString() { + return "PageablePerson{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", hobbies=" + hobbies + + ", shippingAddresses=" + shippingAddresses + + ", _etag='" + _etag + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java new file mode 100644 index 000000000000..987b9fb487b1 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; + +import java.util.List; +import java.util.Objects; + +@Document() +public class PartitionPerson { + + private String id; + + private String firstName; + + @PartitionKey + private String lastName; + + private List hobbies; + + private List
shippingAddresses; + + public PartitionPerson(String id, String firstName, String lastName, List hobbies, List
shippingAddresses) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.hobbies = hobbies; + this.shippingAddresses = shippingAddresses; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public List getHobbies() { + return hobbies; + } + + public void setHobbies(List hobbies) { + this.hobbies = hobbies; + } + + public List
getShippingAddresses() { + return shippingAddresses; + } + + public void setShippingAddresses(List
shippingAddresses) { + this.shippingAddresses = shippingAddresses; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PartitionPerson that = (PartitionPerson) o; + return Objects.equals(id, that.id) && + Objects.equals(firstName, that.firstName) && + Objects.equals(lastName, that.lastName) && + Objects.equals(hobbies, that.hobbies) && + Objects.equals(shippingAddresses, that.shippingAddresses); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName, hobbies, shippingAddresses); + } + + @Override + public String toString() { + return "PartitionPerson{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", hobbies=" + hobbies + + ", shippingAddresses=" + shippingAddresses + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java new file mode 100644 index 000000000000..bef11d622e6f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import java.util.List; +import java.util.Objects; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; + +import org.springframework.data.annotation.Version; + +@Document() +@DocumentIndexingPolicy(includePaths = TestConstants.ORDER_BY_STRING_PATH) +public class Person { + private String id; + private String firstName; + + @PartitionKey + private String lastName; + private List hobbies; + private List
shippingAddresses; + @Version + private String _etag; + + public Person(String id, String firstName, String lastName, List hobbies, List
shippingAddresses) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.hobbies = hobbies; + this.shippingAddresses = shippingAddresses; + } + + public Person() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public List getHobbies() { + return hobbies; + } + + public void setHobbies(List hobbies) { + this.hobbies = hobbies; + } + + public List
getShippingAddresses() { + return shippingAddresses; + } + + public void setShippingAddresses(List
shippingAddresses) { + this.shippingAddresses = shippingAddresses; + } + + public String get_etag() { + return _etag; + } + + public void set_etag(String _etag) { + this._etag = _etag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Person person = (Person) o; + return Objects.equals(id, person.id) && + Objects.equals(firstName, person.firstName) && + Objects.equals(lastName, person.lastName) && + Objects.equals(hobbies, person.hobbies) && + Objects.equals(shippingAddresses, person.shippingAddresses); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName, hobbies, shippingAddresses); + } + + @Override + public String toString() { + return "Person{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", hobbies=" + hobbies + + ", shippingAddresses=" + shippingAddresses + + ", _etag='" + _etag + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java new file mode 100644 index 000000000000..38137e123cea --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document() +@DocumentIndexingPolicy(includePaths = TestConstants.ORDER_BY_STRING_PATH) +public class Project { + + @Id + private String id; + + private String name; + + @PartitionKey + private String creator; + + private Boolean hasReleased; + + private Long starCount; + + private Long forkCount; + + public Project(String id, String name, String creator, Boolean hasReleased, Long starCount, Long forkCount) { + this.id = id; + this.name = name; + this.creator = creator; + this.hasReleased = hasReleased; + this.starCount = starCount; + this.forkCount = forkCount; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCreator() { + return creator; + } + + public void setCreator(String creator) { + this.creator = creator; + } + + public Boolean getHasReleased() { + return hasReleased; + } + + public void setHasReleased(Boolean hasReleased) { + this.hasReleased = hasReleased; + } + + public Long getStarCount() { + return starCount; + } + + public void setStarCount(Long starCount) { + this.starCount = starCount; + } + + public Long getForkCount() { + return forkCount; + } + + public void setForkCount(Long forkCount) { + this.forkCount = forkCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Project project = (Project) o; + return Objects.equals(id, project.id) && + Objects.equals(name, project.name) && + Objects.equals(creator, project.creator) && + Objects.equals(hasReleased, project.hasReleased) && + Objects.equals(starCount, project.starCount) && + Objects.equals(forkCount, project.forkCount); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, creator, hasReleased, starCount, forkCount); + } + + @Override + public String toString() { + return "Project{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", creator='" + creator + '\'' + + ", hasReleased=" + hasReleased + + ", starCount=" + starCount + + ", forkCount=" + forkCount + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java new file mode 100644 index 000000000000..5afb3c615f04 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.azure.data.cosmos.IndexingMode; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; +import java.util.UUID; + +@Document +@DocumentIndexingPolicy(mode = IndexingMode.LAZY) +public class Question { + + @Id + @PartitionKey + private String id = UUID.randomUUID().toString(); + + private String url; + + public Question(String id, String url) { + this.id = id; + this.url = url; + } + + public Question() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Question question = (Question) o; + return Objects.equals(id, question.id) && + Objects.equals(url, question.url); + } + + @Override + public int hashCode() { + return Objects.hash(id, url); + } + + @Override + public String toString() { + return "Question{" + + "id='" + id + '\'' + + ", url='" + url + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java new file mode 100644 index 000000000000..5dd3f7ace423 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.azure.data.cosmos.IndexingMode; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@DocumentIndexingPolicy( + mode = IndexingMode.LAZY, + automatic = TestConstants.INDEXINGPOLICY_AUTOMATIC, + includePaths = { + TestConstants.INCLUDEDPATH_0, + TestConstants.INCLUDEDPATH_1, + TestConstants.INCLUDEDPATH_2, + }, + excludePaths = { + TestConstants.EXCLUDEDPATH_0, + TestConstants.EXCLUDEDPATH_1, + }) +@Document(collection = TestConstants.ROLE_COLLECTION_NAME, + autoCreateCollection = false) +public class Role { + @Id + String id; + + @PartitionKey + String name; + + String level; + + public Role(String id, String name, String level) { + this.id = id; + this.name = name; + this.level = level; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Role role = (Role) o; + return Objects.equals(id, role.id) && + Objects.equals(name, role.name) && + Objects.equals(level, role.level); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, level); + } + + @Override + public String toString() { + return "Role{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", level='" + level + '\'' + + '}'; + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java new file mode 100644 index 000000000000..2b267337818a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +@Document() +@DocumentIndexingPolicy(includePaths = TestConstants.ORDER_BY_STRING_PATH) +public class SortedProject { + + @Id + private String id; + + private String name; + + @PartitionKey + private String creator; + + private Boolean hasReleased; + + private Long starCount; + + private Long forkCount; + + public SortedProject(String id, String name, String creator, Boolean hasReleased, Long starCount, Long forkCount) { + this.id = id; + this.name = name; + this.creator = creator; + this.hasReleased = hasReleased; + this.starCount = starCount; + this.forkCount = forkCount; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCreator() { + return creator; + } + + public void setCreator(String creator) { + this.creator = creator; + } + + public Boolean getHasReleased() { + return hasReleased; + } + + public void setHasReleased(Boolean hasReleased) { + this.hasReleased = hasReleased; + } + + public Long getStarCount() { + return starCount; + } + + public void setStarCount(Long starCount) { + this.starCount = starCount; + } + + public Long getForkCount() { + return forkCount; + } + + public void setForkCount(Long forkCount) { + this.forkCount = forkCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SortedProject that = (SortedProject) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name) && + Objects.equals(creator, that.creator) && + Objects.equals(hasReleased, that.hasReleased) && + Objects.equals(starCount, that.starCount) && + Objects.equals(forkCount, that.forkCount); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, creator, hasReleased, starCount, forkCount); + } + + @Override + public String toString() { + return "SortedProject{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", creator='" + creator + '\'' + + ", hasReleased=" + hasReleased + + ", starCount=" + starCount + + ", forkCount=" + forkCount + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java new file mode 100644 index 000000000000..97d31e1d066a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; + +import java.util.Objects; + +@Document(collection = "#{@dynamicContainer.getContainerName()}") +public class SpELBeanStudent { + private String id; + private String firstName; + private String lastName; + + public SpELBeanStudent(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public SpELBeanStudent() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SpELBeanStudent that = (SpELBeanStudent) o; + return Objects.equals(id, that.id) && + Objects.equals(firstName, that.firstName) && + Objects.equals(lastName, that.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName); + } + + @Override + public String toString() { + return "SpELBeanStudent{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java new file mode 100644 index 000000000000..88c9e6cf40d7 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; + +import java.util.Objects; + +@Document(collection = "${dynamic.collection.name}") +public class SpELPropertyStudent { + private String id; + private String firstName; + private String lastName; + + public SpELPropertyStudent(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public SpELPropertyStudent() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SpELPropertyStudent that = (SpELPropertyStudent) o; + return Objects.equals(id, that.id) && + Objects.equals(firstName, that.firstName) && + Objects.equals(lastName, that.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName); + } + + @Override + public String toString() { + return "SpELPropertyStudent{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java new file mode 100644 index 000000000000..dd30806ceb58 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; + +import java.util.Objects; + +@DocumentIndexingPolicy(includePaths = TestConstants.STARTSWITH_INCLUDEDPATH) +public class Student { + private String id; + private String firstName; + private String lastName; + + public Student(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Student student = (Student) o; + return Objects.equals(id, student.id) && + Objects.equals(firstName, student.firstName) && + Objects.equals(lastName, student.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName); + } + + @Override + public String toString() { + return "Student{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java new file mode 100644 index 000000000000..3a6093ec6b6f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; + +@Document(timeToLive = TestConstants.TIME_TO_LIVE) +public class TimeToLiveSample { + private String id; + + public TimeToLiveSample(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java new file mode 100644 index 000000000000..adf4e4dadf65 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain.inheritance; + +import java.util.Objects; + +public abstract class Shape { + int area; + + public int getArea() { + return area; + } + + public void setArea(int area) { + this.area = area; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Shape shape = (Shape) o; + return area == shape.area; + } + + @Override + public int hashCode() { + return Objects.hash(area); + } + + @Override + public String toString() { + return "Shape{" + "area=" + area + '}'; + } + + public Shape(int area) { + this.area = area; + } + + public Shape() { + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java new file mode 100644 index 000000000000..2574d0a4bea0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.domain.inheritance; + +import org.springframework.data.annotation.Id; + +import java.util.Objects; + +public class Square extends Shape { + @Id + private String id; + + private int length; + + public Square(String id, int length, int area) { + this.id = id; + this.length = length; + this.area = area; + } + + public Square() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + Square square = (Square) o; + return length == square.length && + Objects.equals(id, square.id); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), id, length); + } + + @Override + public String toString() { + return "Square{" + "id='" + id + '\'' + ", length=" + length + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java new file mode 100644 index 000000000000..d893bbc89282 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance; + +import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants; +import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableCosmosRepositories; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource(value = {"classpath:application.properties"}) +@EnableCosmosRepositories +public class PerfConfiguration extends AbstractCosmosConfiguration { + @Value("${cosmosdb.uri:}") + private String cosmosDbUri; + + @Value("${cosmosdb.key:}") + private String cosmosDbKey; + + @Bean + public CosmosDBConfig getConfig() { + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java new file mode 100644 index 000000000000..97d7698ecf54 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance; + +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.sync.CosmosSyncClient; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson; +import com.microsoft.azure.spring.data.cosmosdb.performance.repository.PerfPersonRepository; +import com.microsoft.azure.spring.data.cosmosdb.performance.service.SdkService; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.DatabaseUtils; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.PerfDataProvider; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.*; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = PerfConfiguration.class) +public class PerformanceCompare { + + private static final Logger LOGGER = LoggerFactory.getLogger(PerformanceCompare.class); + + @Value("${perf.recursive.times:20}") + private int recurTimes; + + @Value("${perf.batch.size:5}") + private int batchSize; + + @Value("${perf.acceptance.percentage:15}") + private int acceptanceDiffPercentage; + + private float acceptanceDiff; + + @Autowired + private CosmosSyncClient cosmosSyncClient; + + @Autowired + private CosmosClient asyncClient; + + @Autowired + private PerfPersonRepository repository; + + private static boolean hasInit = false; + private static SdkService sdkService; + private static PerformanceReport report = new PerformanceReport(); + + @Before + public void setUp() throws CosmosClientException { + if (!hasInit) { + DatabaseUtils.createDatabase(cosmosSyncClient, Constants.PERF_DATABASE_NAME); + DatabaseUtils.createContainer(cosmosSyncClient, Constants.PERF_DATABASE_NAME, + Constants.SPRING_COLLECTION_NAME); + DatabaseUtils.createContainer(cosmosSyncClient, + Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME); + + sdkService = new SdkService(cosmosSyncClient, Constants.PERF_DATABASE_NAME, + Constants.SDK_COLLECTION_NAME, asyncClient); + hasInit = true; + } + + acceptanceDiff = (float) acceptanceDiffPercentage / 100; + LOGGER.info("Running performance test for {} time(s), batch size {} and acceptance diff {}.", + recurTimes, batchSize, acceptanceDiff); + } + + @After + public void clear() { + repository.deleteAll(); + sdkService.deleteAll(); + } + + @AfterClass + public static void printReport() { + report.getPerfItems().forEach(System.out::println); + } + + @Test + public void saveOneRecordTest() { + final List personList = PerfDataProvider.getPerfData(recurTimes); + + final long springCost = applyInputListFunc(personList, repository::save); + final long sdkCost = applyInputListFunc(personList, sdkService::save); + + verifyResult(OperationType.SAVE_ONE, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void saveMultipleRecordsTest() { + final List> personList = PerfDataProvider.getMultiPerfData(batchSize, recurTimes); + + final long springCost = acceptInputListFunc(personList, repository::saveAll); + final long sdkCost = acceptInputListFunc(personList, sdkService::saveAll); + + verifyResult(OperationType.SAVE_ALL, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void deleteOneRecordTest() { + final List personList = prepareListData(recurTimes); + + final long springCost = acceptInputListFunc(personList, repository::delete); + final long sdkCost = acceptInputListFunc(personList, sdkService::delete); + + verifyResult(OperationType.DELETE_ONE, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void deleteAllRecordsTest() { + final List> personList = prepareListBatchData(recurTimes, batchSize); + + final long springCost = acceptInputListFunc(personList, repository::deleteAll); + final long sdkCost = acceptInputListFunc(personList, sdkService::deleteAll); + + verifyResult(OperationType.DELETE_ALL, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findByIdTest() { + final List idList = prepareListData(recurTimes).stream().map(PerfPerson::getId) + .collect(Collectors.toList()); + + final long springCost = applyInputListFunc(idList, repository::findById); + final long sdkCost = applyInputListFunc(idList, sdkService::findById); + + verifyResult(OperationType.FIND_BY_ID, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findByMultipleIdsTest() { + final List> idList = listBatchIds(recurTimes, batchSize); + + final long springCost = acceptInputListFunc(idList, repository::findAllById); + final long sdkCost = acceptInputListFunc(idList, sdkService::findAllById); + + verifyResult(OperationType.FIND_BY_IDS, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findAllTest() { + prepareListData(recurTimes); + + final long springCost = getSupplier(recurTimes, repository::findAll); + final long sdkCost = getSupplier(recurTimes, sdkService::findAll); + + verifyResult(OperationType.FIND_ALL, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void deleteAllTest() { + final long springCost = getSupplier(recurTimes, this::springDeleteAll); + final long sdkCost = getSupplier(recurTimes, sdkService::deleteAll); + + verifyResult(OperationType.DELETE_ALL, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findBySortingTest() { + prepareListData(recurTimes); + + final Sort sort = Sort.by(Sort.Direction.ASC, "name"); + final List sortList = buildSortList(sort, recurTimes); + + final long springCost = applyInputListFunc(sortList, repository::findAll); + final long sdkCost = applyInputListFunc(sortList, sdkService::searchDocuments); + + verifyResult(OperationType.FIND_BY_SORT, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findByPagingTest() { + prepareListData(recurTimes); + int pageSize = recurTimes / 2; + pageSize = pageSize >= 1 ? pageSize : 1; + + final long springCost = runConsumerForTimes(recurTimes, pageSize, this::queryTwoPages); + final long sdkCost = runConsumerForTimes(recurTimes, pageSize, sdkService::queryTwoPages); + + verifyResult(OperationType.FIND_BY_PAGING, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void findByFieldTest() { + final List data = prepareListData(recurTimes); + + final String name = data.get(recurTimes / 2).getName(); + + final long springCost = runFunctionForTimes(recurTimes, name, repository::findByName); + final long sdkCost = runConsumerForTimes(recurTimes, name, sdkService::findByName); + + verifyResult(OperationType.FIND_BY_FIELD, springCost, sdkCost, acceptanceDiff); + } + + @Test + public void countTest() { + prepareListData(recurTimes); + + final long springCost = getSupplier(recurTimes, repository::count); + final long sdkCost = getSupplier(recurTimes, sdkService::count); + + verifyResult(OperationType.COUNT, springCost, sdkCost, acceptanceDiff); + } + + /** + * Check whether two time cost fall into the acceptable range. + * + * @param timeCostSpring + * @param timeCostSdk + * @param acceptanceDiff The acceptable diff between two time cost. + */ + private void assertPerf(long timeCostSpring, long timeCostSdk, float acceptanceDiff) { + final long diff = timeCostSpring - timeCostSdk; + final float actualDiff = (float) diff / timeCostSdk; + + assertThat(actualDiff).isLessThan(acceptanceDiff); + } + + private void verifyResult(OperationType type, long timeCostSpring, long timeCostSdk, float acceptanceDiff) { + report.addItem(new PerfItem(type, timeCostSpring, timeCostSdk, recurTimes)); + assertPerf(timeCostSpring, timeCostSdk, acceptanceDiff); + } + + private boolean springDeleteAll() { + repository.deleteAll(); + return true; // To provide return value for Supplier + } + + private List buildSortList(Sort sort, int times) { + final List sorts = new ArrayList<>(); + for (int i = 0; i < times; i++) { + sorts.add(sort); + } + + return sorts; + } + + private void queryTwoPages(int pageSize) { + final Pageable pageable = new CosmosPageRequest(0, pageSize, null); + final Page page = this.repository.findAll(pageable); + this.repository.findAll(page.getPageable()); + } + + private List prepareListData(int count) { + final List personList = PerfDataProvider.getPerfData(count); + + applyInputListFunc(personList, repository::save); + applyInputListFunc(personList, sdkService::save); + + return personList; + } + + + private List> prepareListBatchData(int times, int batchSize) { + final List> personList = PerfDataProvider.getMultiPerfData(batchSize, times); + + applyInputListFunc(personList, repository::saveAll); + applyInputListFunc(personList, sdkService::saveAll); + + return personList; + } + + private List> listBatchIds(int times, int batchSize) { + return prepareListBatchData(times, batchSize).stream() + .map(iterable -> { + final List batchIds = new ArrayList<>(); + iterable.forEach(person -> batchIds.add(person.getId())); + return batchIds; + }).collect(Collectors.toList()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java new file mode 100644 index 000000000000..0209ef5deef7 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class PerformanceReport { + private static final String NEW_LINE = System.lineSeparator(); + + private final List perfItems = new ArrayList<>(); + + public void addItem(PerfItem item) { + perfItems.add(item); + } + + public List getPerfItems() { + return this.perfItems; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + perfItems.forEach(item -> sb.append(item.toString()).append(NEW_LINE)); + + return sb.toString(); + } +} + +class PerfItem { + private OperationType type; + private long springCost; + private long sdkCost; + private int times; + private float diffToSdk; + + public PerfItem(OperationType type, long springCost, long sdkCost, int times) { + this.type = type; + this.springCost = springCost; + this.sdkCost = sdkCost; + this.times = times; + this.diffToSdk = (float) (springCost - sdkCost) / sdkCost; + } + + public OperationType getType() { + return type; + } + + public void setType(OperationType type) { + this.type = type; + } + + public long getSpringCost() { + return springCost; + } + + public void setSpringCost(long springCost) { + this.springCost = springCost; + } + + public long getSdkCost() { + return sdkCost; + } + + public void setSdkCost(long sdkCost) { + this.sdkCost = sdkCost; + } + + public int getTimes() { + return times; + } + + public void setTimes(int times) { + this.times = times; + } + + public float getDiffToSdk() { + return diffToSdk; + } + + public void setDiffToSdk(float diffToSdk) { + this.diffToSdk = diffToSdk; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PerfItem perfItem = (PerfItem) o; + return springCost == perfItem.springCost && + sdkCost == perfItem.sdkCost && + times == perfItem.times && + Float.compare(perfItem.diffToSdk, diffToSdk) == 0 && + type == perfItem.type; + } + + @Override + public int hashCode() { + return Objects.hash(type, springCost, sdkCost, times, diffToSdk); + } + + @Override + public String toString() { + return "[type=" + type.toString() + ", springCost=" + springCost + ", sdkCost=" + sdkCost + ", times=" + + times + ", diffToSdk=" + (diffToSdk * 100 + "%") + "];"; + } +} + +enum OperationType { + SAVE_ONE("save one"), SAVE_ALL("save all"), DELETE_ONE("delete one"), DELETE_ALL("delete all"), + FIND_BY_ID("find by id"), FIND_BY_IDS("find by ids"), FIND_ALL("find all"), FIND_BY_SORT("find by sort"), + FIND_BY_PAGING("find by paging"), FIND_BY_FIELD("find by field"), COUNT("count"); + + private String type; + + OperationType(String type) { + this.type = type; + } + + public String toString() { + return this.type; + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java new file mode 100644 index 000000000000..2f8c5b0d83ec --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.performance.domain; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants; + +import java.util.Objects; + +@Document(collection = Constants.SPRING_COLLECTION_NAME) +@DocumentIndexingPolicy(includePaths = TestConstants.ORDER_BY_STRING_PATH) +public class PerfPerson { + private String id; + private String name; + + public PerfPerson(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PerfPerson that = (PerfPerson) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + return "PerfPerson{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java new file mode 100644 index 000000000000..7f41ee743800 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.repository; + +import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface PerfPersonRepository extends CosmosRepository { + List findAll(Sort sort); + + List findByName(String name); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java new file mode 100644 index 000000000000..bc18a1831630 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.service; + +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.CosmosItemRequestOptions; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.PartitionKey; +import com.azure.data.cosmos.sync.CosmosSyncClient; +import com.google.gson.Gson; +import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson; +import com.microsoft.azure.spring.data.cosmosdb.performance.utils.DatabaseUtils; +import org.assertj.core.util.Lists; +import org.springframework.data.domain.Sort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +public class SdkService { + private static Gson gson = new Gson(); + + private final CosmosSyncClient cosmosSyncClient; + private final String dbName; + private final String containerName; + + public SdkService(CosmosSyncClient client, String dbName, String containerName, CosmosClient asyncClient) { + this.cosmosSyncClient = client; + this.dbName = dbName; + this.containerName = containerName; + } + + public PerfPerson save(PerfPerson person) { + try { + final String personJson = gson.toJson(person); + final CosmosItemProperties personDoc = new CosmosItemProperties(personJson); + + final CosmosItemProperties doc = cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .createItem(personDoc) + .properties(); + + return gson.fromJson(doc.toJson(), PerfPerson.class); + } catch (Exception e) { + throw new IllegalStateException(e); // Runtime exception to fail directly + } + } + + public List saveAll(Iterable personIterable) { + final List result = new ArrayList<>(); + personIterable.forEach(person -> result.add(save(person))); + + return result; + } + + public void delete(PerfPerson person) { + try { + final String docLink = DatabaseUtils.getDocumentLink(dbName, containerName, person.getId()); + cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .getItem(person.getId(), PartitionKey.None) + .delete(new CosmosItemRequestOptions()); + + } catch (CosmosClientException e) { + throw new IllegalStateException(e); // Runtime exception to fail directly + } + } + + public void deleteAll(Iterable personIterable) { + personIterable.forEach(person -> delete(person)); + } + + public CosmosItemProperties findById(String id) { + final Iterator> feedResponseIterator = + cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .queryItems("SELECT * FROM " + containerName + " WHERE " + + containerName + ".id='" + id + "'", new FeedOptions()); + CosmosItemProperties itemProperties = null; + if (feedResponseIterator.hasNext()) { + final List results = feedResponseIterator.next().results(); + if (!results.isEmpty()) { + itemProperties = results.get(0); + } + } + + return itemProperties; + } + + public List findAllById(Iterable ids) { + final String idsInList = String.join(",", + Arrays.asList(ids).stream().map(id -> "'" + id + "'").collect(Collectors.toList())); + final String sql = "SELECT * FROM " + containerName + " WHERE " + containerName + ".id IN (" + + idsInList + ")"; + + final FeedOptions feedOptions = new FeedOptions(); + feedOptions.enableCrossPartitionQuery(true); + + final List docs = new ArrayList<>(); + + final Iterator> feedResponseIterator = cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .queryItems(sql, feedOptions); + while (feedResponseIterator.hasNext()) { + final FeedResponse next = feedResponseIterator.next(); + docs.addAll(next.results()); + } + + + return fromDocuments(docs); + } + + public List findAll() { + final String sql = "SELECT * FROM " + containerName; + final List docs = getCosmosItemPropertiesList(sql); + return fromDocuments(docs); + } + + public boolean deleteAll() { + final String sql = "SELECT * FROM " + containerName; + final List documents = getCosmosItemPropertiesList(sql); + + documents.forEach(document -> { + try { + cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .getItem(document.id(), PartitionKey.None) + .delete(new CosmosItemRequestOptions().partitionKey(PartitionKey.None)); + } catch (CosmosClientException e) { + throw new IllegalStateException(e); + } + }); + + return true; + } + + private List getCosmosItemPropertiesList(String sql) { + final List documents = new ArrayList<>(); + final Iterator> feedResponseIterator = + cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .queryItems(sql, new FeedOptions().enableCrossPartitionQuery(true)); + while (feedResponseIterator.hasNext()) { + final FeedResponse next = feedResponseIterator.next(); + documents.addAll(next.results()); + } + return documents; + } + + public List searchDocuments(Sort sort) { + final Sort.Order order = sort.iterator().next(); // Only one Order supported + final String sql = "SELECT * FROM " + containerName + " ORDER BY " + containerName + "." + + order.getProperty() + " " + order.getDirection().name(); + final List docs = getCosmosItemPropertiesList(sql); + + return fromDocuments(docs); + } + + public long count() { + final String sql = "SELECT VALUE COUNT(1) FROM " + containerName; + final Iterator> feedResponseIterator = cosmosSyncClient.getDatabase(dbName) + .getContainer(containerName) + .queryItems(sql, new FeedOptions()); + final Object result = feedResponseIterator.next().results().get(0).get("_aggregate"); + + return result instanceof Integer ? Long.valueOf((Integer) result) : (Long) result; + } + + public List findByName(String name) { + final String sql = "SELECT * FROM " + containerName + " WHERE " + containerName + ".name='" + + name + "'"; + final Iterator result = getCosmosItemPropertiesList(sql).iterator(); + return fromDocuments(Lists.newArrayList(result)); + } + + public void queryTwoPages(int pageSize) { + final FeedOptions options = new FeedOptions(); + options.maxItemCount(pageSize); + options.requestContinuation(null); + + searchBySize(pageSize, options); + searchBySize(pageSize, options); + } + + private List searchBySize(int size, FeedOptions options) { + final String sql = "SELECT * FROM " + containerName; + + final Iterator it = getCosmosItemPropertiesList(sql).iterator(); + final List entities = new ArrayList<>(); + int i = 0; + while (it.hasNext() && i++ < size) { + // This convert here is in order to mock data conversion in real use case, in order to compare with + // Spring Data mapping + final CosmosItemProperties d = it.next(); + final PerfPerson entity = gson.fromJson(d.toJson(), PerfPerson.class); + entities.add(entity); + } + + count(); // Mock same behavior with Spring pageable query, requires total elements count + + return entities; + } + + private List fromDocuments(List documents) { + return documents.stream().map(d -> gson.fromJson(d.toJson(), PerfPerson.class)) + .collect(Collectors.toList()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java new file mode 100644 index 000000000000..0813cd7fb40d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.utils; + +public class Constants { + public static final String PERF_DATABASE_NAME = "perf_database"; + public static final String SPRING_COLLECTION_NAME = "spring_perf_coll"; + public static final String SDK_COLLECTION_NAME = "sdk_perf_coll"; +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java new file mode 100644 index 000000000000..6612ff254070 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.utils; + +import com.azure.data.cosmos.CosmosClientException; +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.IncludedPath; +import com.azure.data.cosmos.IndexingPolicy; +import com.azure.data.cosmos.PartitionKeyDefinition; +import com.azure.data.cosmos.internal.RequestOptions; +import com.azure.data.cosmos.sync.CosmosSyncClient; + +import java.util.Collections; + +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ORDER_BY_STRING_PATH; + +public class DatabaseUtils { + public static void createDatabase(CosmosSyncClient documentClient, String databaseName) + throws CosmosClientException { + try { + // Can use sync api once ready + documentClient.getDatabase(databaseName).delete(); + } catch (Exception e) { + // Ignore delete failure + } + + documentClient.createDatabase(databaseName); + } + + public static void deleteContainer(CosmosSyncClient documentClient, String databaseName, String containerName) + throws CosmosClientException{ + final RequestOptions requestOptions = new RequestOptions(); + requestOptions.setOfferThroughput(1000); + + documentClient.getDatabase(databaseName).getContainer(containerName).delete(); + } + + public static void createContainer(CosmosSyncClient documentClient, String databaseName, String containerName) + throws CosmosClientException { + final CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, + new PartitionKeyDefinition().paths(Collections.singletonList("/mypk"))); + + final IndexingPolicy policy = new IndexingPolicy(); + policy.setIncludedPaths(Collections.singletonList(new IncludedPath(ORDER_BY_STRING_PATH))); + containerProperties.indexingPolicy(policy); + + documentClient.getDatabase(databaseName).createContainer(containerProperties); + } + + public static String getDocumentLink(String databaseName, String containerName, Object documentId) { + return getContainerLink(databaseName, containerName) + "/docs/" + documentId; + } + + public static String getDatabaseLink(String databaseName) { + return "dbs/" + databaseName; + } + + public static String getContainerLink(String databaseName, String containerName) { + return getDatabaseLink(databaseName) + "/colls/" + containerName; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java new file mode 100644 index 000000000000..ba890c121215 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.utils; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class FunctionUtils { + /** + * Run supplier for times. + * @param times How many times the supplier will run. + * @param supplier Supplier to run. + * @param + * @return time cost in milli-seconds of running the supplier for times + */ + public static long getSupplier(int times, Supplier supplier) { + final long startTime = System.currentTimeMillis(); + for (int i = 0; i < times; i++) { + supplier.get(); + } + final long endTime = System.currentTimeMillis(); + + return endTime - startTime; + } + + + /** + * Run function for each element in the inputList + * @param inputList list of input data to be processed by function + * @param function @see java.util.function.Function to process data in the inputList + * @param the type of the input to the function + * @param the type of the result of the function + * @return time cost in milli-seconds of processing the whole inputList by function + */ + public static long applyInputListFunc(List inputList, Function function) { + final long startTime = System.currentTimeMillis(); + inputList.forEach(function::apply); + final long endTime = System.currentTimeMillis(); + + return endTime - startTime; + } + + /** + * + * @param times How many times the function will apply + * @param argument argument for the function + * @param function @see java.util.function.Function to process the argument + * @param the type of the input to the function + * @param the type of the result of the function + * @return time cost in milli-seconds of running the function for times + */ + public static long runFunctionForTimes(int times, T argument, Function function) { + final long startTime = System.currentTimeMillis(); + for (int i = 0; i < times; i++) { + function.apply(argument); + } + final long endTime = System.currentTimeMillis(); + + return endTime - startTime; + } + + /** + * Run consumer for each element in the inputList + * @param inputList list of input data to be processed by consumer + * @param consumer @see java.util.function.Consumer to process data in the inputList + * @param the type of the input to the consumer + * @return time cost in milli-seconds of processing the whole inputList by consumer + */ + public static long acceptInputListFunc(List inputList, Consumer consumer) { + final long startTime = System.currentTimeMillis(); + inputList.forEach(consumer::accept); + final long endTime = System.currentTimeMillis(); + + return endTime - startTime; + } + + /** + * Run consumer with given argument for given times. + * @param times How many times the consumer will run + * @param argument argument for the consumer + * @param consumer @see java.util.function.Consumer to process the input + * @param the type of the input to the consumer + * @return time cost in milli-seconds of running the consumer for times + */ + public static long runConsumerForTimes(int times, T argument, Consumer consumer) { + final long startTime = System.currentTimeMillis(); + for (int i = 0; i < times; i++) { + consumer.accept(argument); + } + final long endTime = System.currentTimeMillis(); + + return endTime - startTime; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java new file mode 100644 index 000000000000..3c5472ca8465 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.performance.utils; + +import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson; +import org.assertj.core.util.Lists; + +import java.util.List; +import java.util.UUID; + +public class PerfDataProvider { + public static List getPerfData(int count) { + final List personList = Lists.newArrayList(); + + for (int i = 1; i <= count; i++) { + final PerfPerson person = new PerfPerson(randomId(), "fake name-" + randomSuffix()); + personList.add(person); + } + + return personList; + } + + public static List> getMultiPerfData(int size, int listCount) { + final List> personList = Lists.newArrayList(); + + for (int i = 0; i < listCount; i++) { + personList.add(getPerfData(size)); + } + + return personList; + } + + private static String randomId() { + return UUID.randomUUID().toString().substring(0, 10); + } + + private static String randomSuffix() { + // It's not random, but just for distinguishing + return UUID.randomUUID().toString().substring(0, 4); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java new file mode 100644 index 000000000000..920fc29a5327 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.azure.data.cosmos.IndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.domain.NoDBAnnotationPerson; +import com.microsoft.azure.spring.data.cosmosdb.domain.Role; +import com.microsoft.azure.spring.data.cosmosdb.domain.TimeToLiveSample; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.Before; +import org.junit.Test; +import org.springframework.util.Assert; + + +public class CosmosAnnotationUnitTest { + private CosmosEntityInformation personInfo; + private CosmosEntityInformation roleInfo; + + @Before + public void setUp() { + personInfo = new CosmosEntityInformation<>(NoDBAnnotationPerson.class); + roleInfo = new CosmosEntityInformation<>(Role.class); + } + + @Test + public void testDefaultIndexingPolicyAnnotation() { + final IndexingPolicy policy = personInfo.getIndexingPolicy(); + final Document documentAnnotation = NoDBAnnotationPerson.class.getAnnotation(Document.class); + final DocumentIndexingPolicy policyAnnotation = + NoDBAnnotationPerson.class.getAnnotation(DocumentIndexingPolicy.class); + + Assert.isNull(documentAnnotation, "NoDBAnnotationPerson class should not have Document annotation"); + Assert.isNull(policyAnnotation, "NoDBAnnotationPerson class should not have DocumentIndexingPolicy annotation"); + Assert.notNull(policy, "NoDBAnnotationPerson class collection policy should not be null"); + + // ContainerName, RequestUnit, Automatic and IndexingMode + Assert.isTrue(personInfo.getContainerName().equals(NoDBAnnotationPerson.class.getSimpleName()), + "should be default collection name"); + Assert.isTrue(personInfo.getRequestUnit() == TestConstants.DEFAULT_REQUEST_UNIT, + "should be default request unit"); + Assert.isTrue(policy.automatic() == TestConstants.DEFAULT_INDEXINGPOLICY_AUTOMATIC, + "should be default indexing policy automatic"); + Assert.isTrue(policy.indexingMode() == TestConstants.DEFAULT_INDEXINGPOLICY_MODE, + "should be default indexing policy mode"); + + // IncludedPaths and ExcludedPaths + // We do not use testIndexingPolicyPathsEquals generic here, for unit test do not create cosmosdb instance, + // and the paths of policy will never be set from azure service. + // testIndexingPolicyPathsEquals(policy.getIncludedPaths(), TestConstants.DEFAULT_INCLUDEDPATHS); + // testIndexingPolicyPathsEquals(policy.getExcludedPaths(), TestConstants.DEFAULT_EXCLUDEDPATHS); + Assert.isTrue(policy.includedPaths().isEmpty(), "default includedpaths size must be 0"); + Assert.isTrue(policy.excludedPaths().isEmpty(), "default excludedpaths size must be 0"); + } + + @Test + public void testIndexingPolicyAnnotation() { + final IndexingPolicy policy = roleInfo.getIndexingPolicy(); + final Document documentAnnotation = Role.class.getAnnotation(Document.class); + final DocumentIndexingPolicy policyAnnotation = Role.class.getAnnotation(DocumentIndexingPolicy.class); + + // ContainerName, RequestUnit, Automatic and IndexingMode + Assert.notNull(documentAnnotation, "NoDBAnnotationPerson class should have Document annotation"); + Assert.notNull(policyAnnotation, "NoDBAnnotationPerson class should have DocumentIndexingPolicy annotation"); + Assert.notNull(policy, "NoDBAnnotationPerson class collection policy should not be null"); + + Assert.isTrue(roleInfo.getContainerName().equals(TestConstants.ROLE_COLLECTION_NAME), + "should be Role(class) collection name"); + Assert.isTrue(roleInfo.getRequestUnit() == TestConstants.REQUEST_UNIT, + "should be Role(class) request unit"); + Assert.isTrue(policy.automatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC, + "should be Role(class) indexing policy automatic"); + Assert.isTrue(policy.indexingMode() == TestConstants.INDEXINGPOLICY_MODE, + "should be Role(class) indexing policy mode"); + + // IncludedPaths and ExcludedPaths + TestUtils.testIndexingPolicyPathsEquals(policy.includedPaths(), TestConstants.INCLUDEDPATHS); + TestUtils.testIndexingPolicyPathsEquals(policy.excludedPaths(), TestConstants.EXCLUDEDPATHS); + } + + @Test + public void testAutoCreateCollectionAnnotation() { + final boolean autoCreateCollectionRoleInfo = roleInfo.isAutoCreateContainer(); + final boolean autoCreateCollectionPersonInfo = personInfo.isAutoCreateContainer(); + + Assert.isTrue(!autoCreateCollectionRoleInfo, "autoCreateContainer in role should be false"); + Assert.isTrue(autoCreateCollectionPersonInfo, "autoCreateContainer in person should be true"); + } + + @Test + public void testDefaultDocumentAnnotationTimeToLive() { + final Integer timeToLive = personInfo.getTimeToLive(); + + Assert.notNull(timeToLive, "timeToLive should not be null"); + Assert.isTrue(timeToLive == TestConstants.DEFAULT_TIME_TO_LIVE, "should be default time to live"); + } + + @Test + public void testDocumentAnnotationTimeToLive() { + final CosmosEntityInformation info = + new CosmosEntityInformation<>(TimeToLiveSample.class); + final Integer timeToLive = info.getTimeToLive(); + + Assert.notNull(timeToLive, "timeToLive should not be null"); + Assert.isTrue(timeToLive == TestConstants.TIME_TO_LIVE, "should be the same time to live"); + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java new file mode 100644 index 000000000000..117d3bbf74ae --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SimpleCosmosRepositoryIllegalTest { + private SimpleCosmosRepository repository; + + @Mock + CosmosOperations dbOperations; + @Mock + CosmosEntityInformation entityInformation; + + @Before + public void setUp() { + repository = new SimpleCosmosRepository<>(entityInformation, dbOperations); + } + + @Test(expected = IllegalArgumentException.class) + public void deleteNullShouldFail() { + repository.delete(null); + } + + @Test(expected = IllegalArgumentException.class) + public void deleteIterableNullShouldFail() { + repository.deleteAll(null); + } + + @Test(expected = IllegalArgumentException.class) + public void deleteNullIdShouldFail() { + repository.deleteById(null); + } + + @Test(expected = IllegalArgumentException.class) + public void existsNullIdShouldFail() { + repository.existsById(null); + } + + @Test(expected = IllegalArgumentException.class) + public void findNullIterableIdsShouldFail() { + repository.findAllById(null); + } + + @Test(expected = IllegalArgumentException.class) + public void findByNullIdShouldFail() { + repository.findById(null); + } + + @Test(expected = IllegalArgumentException.class) + public void saveNullShouldFail() { + repository.save(null); + } + + @Test(expected = IllegalArgumentException.class) + public void saveNullIterableShouldFail() { + repository.saveAll(null); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java new file mode 100644 index 000000000000..6ec48cb66bc3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository; +import org.assertj.core.util.Lists; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SimpleCosmosRepositoryUnitTest { + private static final Person TEST_PERSON = + new Person(TestConstants.ID_1, TestConstants.FIRST_NAME, TestConstants.LAST_NAME, + TestConstants.HOBBIES, TestConstants.ADDRESSES); + + private static final String PARTITION_VALUE_REQUIRED_MSG = + "PartitionKey value must be supplied for this operation."; + + private SimpleCosmosRepository repository; + @Mock + CosmosOperations cosmosOperations; + @Mock + CosmosEntityInformation entityInformation; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + when(entityInformation.getJavaType()).thenReturn(Person.class); + when(entityInformation.getContainerName()).thenReturn(Person.class.getSimpleName()); + when(cosmosOperations.findAll(anyString(), any())).thenReturn(Arrays.asList(TEST_PERSON)); + + repository = new SimpleCosmosRepository<>(entityInformation, cosmosOperations); + } + + @Test + public void testSave() { + repository.save(TEST_PERSON); + + final List result = Lists.newArrayList(repository.findAll()); + assertEquals(1, result.size()); + assertEquals(TEST_PERSON, result.get(0)); + } + + @Test + public void testFindOne() { + when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(TEST_PERSON); + + repository.save(TEST_PERSON); + + final Person result = repository.findById(TEST_PERSON.getId()).get(); + assertEquals(TEST_PERSON, result); + } + + @Test + public void testFindOneExceptionForPartitioned() { + expectedException.expect(UnsupportedOperationException.class); + expectedException.expectMessage(PARTITION_VALUE_REQUIRED_MSG); + + repository.save(TEST_PERSON); + + when(cosmosOperations.findById(anyString(), anyString(), any())) + .thenThrow(new UnsupportedOperationException(PARTITION_VALUE_REQUIRED_MSG)); + + final Person result = repository.findById(TEST_PERSON.getId()).get(); + } + + @Test + public void testUpdate() { + final List
updatedAddress = + Arrays.asList(new Address(TestConstants.POSTAL_CODE, TestConstants.UPDATED_CITY, + TestConstants.UPDATED_STREET)); + final Person updatedPerson = + new Person(TEST_PERSON.getId(), TestConstants.UPDATED_FIRST_NAME, TestConstants.UPDATED_LAST_NAME, + TestConstants.UPDATED_HOBBIES, updatedAddress); + repository.save(updatedPerson); + + when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(updatedPerson); + + final Person result = repository.findById(TEST_PERSON.getId()).get(); + assertEquals(updatedPerson, result); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java new file mode 100644 index 000000000000..573ad516fad1 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository; + +import com.azure.data.cosmos.ConsistencyLevel; +import com.azure.data.cosmos.internal.RequestOptions; +import com.microsoft.azure.spring.data.cosmosdb.common.DynamicContainer; +import com.microsoft.azure.spring.data.cosmosdb.common.ResponseDiagnosticsTestUtils; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableCosmosRepositories; +import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableReactiveCosmosRepositories; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.util.StringUtils; + +@Configuration +@PropertySource(value = {"classpath:application.properties"}) +@EnableCosmosRepositories +@EnableReactiveCosmosRepositories +public class TestRepositoryConfig extends AbstractCosmosConfiguration { + @Value("${cosmosdb.uri:}") + private String cosmosDbUri; + + @Value("${cosmosdb.key:}") + private String cosmosDbKey; + + @Value("${cosmosdb.connection-string:}") + private String connectionString; + + @Value("${cosmosdb.database:}") + private String database; + + @Value("${cosmosdb.populateQueryMetrics}") + private boolean populateQueryMetrics; + + private RequestOptions getRequestOptions() { + final RequestOptions options = new RequestOptions(); + + options.setConsistencyLevel(ConsistencyLevel.SESSION); +// options.setDisableRUPerMinuteUsage(true); + options.setScriptLoggingEnabled(true); + + return options; + } + + @Bean + public ResponseDiagnosticsTestUtils responseDiagnosticsTestUtils() { + return new ResponseDiagnosticsTestUtils(); + } + + @Bean + public CosmosDBConfig getConfig() { + final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; + final RequestOptions options = getRequestOptions(); + final CosmosDBConfig.CosmosDBConfigBuilder builder; + + if (StringUtils.hasText(this.cosmosDbUri) && StringUtils.hasText(this.cosmosDbKey)) { + builder = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName); + } else { + builder = CosmosDBConfig.builder(connectionString, dbName); + } + return builder.requestOptions(options) + .populateQueryMetrics(populateQueryMetrics) + .responseDiagnosticsProcessor(responseDiagnosticsTestUtils().getResponseDiagnosticsProcessor()) + .build(); + } + + @Bean + public DynamicContainer dynamicContainer() { + return new DynamicContainer(TestConstants.DYNAMIC_BEAN_COLLECTION_NAME); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java new file mode 100644 index 000000000000..b6960ab484c3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.type.StandardAnnotationMetadata; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource; +import org.springframework.data.repository.config.RepositoryConfiguration; +import org.springframework.data.repository.config.RepositoryConfigurationSource; + +import java.util.Collection; + +import static org.assertj.core.api.Assertions.fail; + +public class CosmosRepositoryConfigurationExtensionUnitTest { + + StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(Config.class, true); + ResourceLoader loader = new PathMatchingResourcePatternResolver(); + Environment environment = new StandardEnvironment(); + RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata, + EnableCosmosRepositories.class, loader, environment, new DefaultListableBeanFactory()); + + private static void assertHashRepo(Class repositoryInterface, + Collection> configs) { + for (final RepositoryConfiguration config : configs) { + if (config.getRepositoryInterface().equals(repositoryInterface.getName())) { + return; + } + } + + fail("expected to find config for repository interface " + + repositoryInterface.getName() + ", but got: " + configs.toString()); + } + + @Test + public void isStrictMatchIfRepositoryExtendsStoreSpecificBase() { + final CosmosRepositoryConfigurationExtension extension = new CosmosRepositoryConfigurationExtension(); + assertHashRepo(TestRepository.class, extension.getRepositoryConfigurations(configurationSource, loader, true)); + } + + interface TestRepository extends CosmosRepository { + } + + @EnableCosmosRepositories(considerNestedRepositories = true) + static class Config { + + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java new file mode 100644 index 000000000000..1e32fb0fe25b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.azure.spring.data.cosmosdb.repository.config; + +import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository; +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.type.StandardAnnotationMetadata; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource; +import org.springframework.data.repository.config.RepositoryConfiguration; +import org.springframework.data.repository.config.RepositoryConfigurationSource; + +import java.util.Collection; + +import static org.assertj.core.api.Assertions.fail; + +public class ReactiveCosmosRepositoryConfigurationExtensionUnitTest { + + StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(Config.class, true); + ResourceLoader loader = new PathMatchingResourcePatternResolver(); + Environment environment = new StandardEnvironment(); + RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata, + EnableReactiveCosmosRepositories.class, loader, environment, new DefaultListableBeanFactory()); + + private static void assertHashRepo(Class repositoryInterface, + Collection> configs) { + for (final RepositoryConfiguration config : configs) { + if (config.getRepositoryInterface().equals(repositoryInterface.getName())) { + return; + } + } + + fail("expected to find config for repository interface " + + repositoryInterface.getName() + ", but got: " + configs.toString()); + } + + @Test + public void isStrictMatchIfRepositoryExtendsStoreSpecificBase() { + final ReactiveCosmosRepositoryConfigurationExtension extension = + new ReactiveCosmosRepositoryConfigurationExtension(); + assertHashRepo(TestRepository.class, + extension.getRepositoryConfigurations(configurationSource, loader, true)); + } + + interface TestRepository extends ReactiveCosmosRepository { + } + + @EnableReactiveCosmosRepositories(considerNestedRepositories = true) + static class Config { + + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java new file mode 100644 index 000000000000..78526ac34dd6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.AddressRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class AddressRepositoryIT { + + private static final Address TEST_ADDRESS1_PARTITION1 = new Address( + TestConstants.POSTAL_CODE, TestConstants.STREET, TestConstants.CITY); + private static final Address TEST_ADDRESS2_PARTITION1 = new Address( + TestConstants.POSTAL_CODE_0, TestConstants.STREET_0, TestConstants.CITY); + private static final Address TEST_ADDRESS1_PARTITION2 = new Address( + TestConstants.POSTAL_CODE_1, TestConstants.STREET_1, TestConstants.CITY_0); + private static final Address TEST_ADDRESS4_PARTITION3 = new Address( + TestConstants.POSTAL_CODE, TestConstants.STREET_2, TestConstants.CITY_1); + + private static final CosmosEntityInformation entityInformation + = new CosmosEntityInformation<>(Address.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + AddressRepository repository; + + @Autowired + private CosmosTemplate template; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + repository.save(TEST_ADDRESS1_PARTITION1); + repository.saveAll(Lists.newArrayList(TEST_ADDRESS1_PARTITION2, + TEST_ADDRESS2_PARTITION1, TEST_ADDRESS4_PARTITION3)); + isSetupDone = true; + } + + @After + public void cleanup() { + repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAll() { + // findAll cross partition + final List
result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(4); + } + + @Test + public void testFindByIdWithPartitionKey() { + final Optional
addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(), + new PartitionKey(entityInformation.getPartitionKeyFieldValue(TEST_ADDRESS1_PARTITION1))); + + if (!addressById.isPresent()) { + fail("address not found"); + return; + } + assertThat(addressById.get()).isEqualTo(TEST_ADDRESS1_PARTITION1); + } + + @Test + public void testFindByIdForPartitionedCollection() { + final List
addresses = repository.findByPostalCode(TestConstants.POSTAL_CODE); + + assertThat(addresses.size()).isEqualTo(2); + assertThat(addresses.get(0).getPostalCode()).isEqualTo(TestConstants.POSTAL_CODE); + assertThat(addresses.get(1).getPostalCode()).isEqualTo(TestConstants.POSTAL_CODE); + } + + @Test + public void testFindByPartitionedCity() { + final String city = TEST_ADDRESS1_PARTITION1.getCity(); + final List
result = TestUtils.toList(repository.findByCity(city)); + + assertThat(result.size()).isEqualTo(2); + assertThat(result.get(0).getCity()).isEqualTo(city); + assertThat(result.get(1).getCity()).isEqualTo(city); + } + + @Test + public void testFindByStreetOrCity() { + final String city = TEST_ADDRESS1_PARTITION1.getCity(); + final String street = TEST_ADDRESS1_PARTITION2.getStreet(); + + final List
result = repository.findByStreetOrCity(street, city); + final List
reference = Arrays.asList( + TEST_ADDRESS1_PARTITION1, TEST_ADDRESS1_PARTITION2, TEST_ADDRESS2_PARTITION1); + + result.sort(Comparator.comparing(Address::getPostalCode)); + reference.sort(Comparator.comparing(Address::getPostalCode)); + + Assert.assertEquals(reference.size(), result.size()); + Assert.assertEquals(reference, result); + } + + @Test + public void testCount() { + final long count = repository.count(); + assertThat(count).isEqualTo(4); + + repository.deleteByCity(TestConstants.CITY); + final long newCount = repository.count(); + assertThat(newCount).isEqualTo(2); + } + + @Test + public void deleteWithoutPartitionedColumnShouldFail() { + expectedException.expect(Exception.class); + + repository.deleteById(TEST_ADDRESS1_PARTITION1.getPostalCode()); + } + + @Test + public void canDeleteByIdAndPartitionedCity() { + final long count = repository.count(); + assertThat(count).isEqualTo(4); + + repository.deleteByPostalCodeAndCity( + TEST_ADDRESS1_PARTITION1.getPostalCode(), TEST_ADDRESS1_PARTITION1.getCity()); + + final List
result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(3); + } + + @Test + public void canDeleteByPartitionedCity() { + final long count = repository.count(); + assertThat(count).isEqualTo(4); + + repository.deleteByCity(TEST_ADDRESS1_PARTITION1.getCity()); + + final List
result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(2); + assertThat(result.get(0).getCity()).isNotEqualTo(TEST_ADDRESS1_PARTITION1.getCity()); + } + + @Test + public void testDeleteByIdAndPartitionKey() { + final long count = repository.count(); + assertThat(count).isEqualTo(4); + + Optional
addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(), + new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity())); + assertThat(addressById.isPresent()).isTrue(); + + repository.deleteById(TEST_ADDRESS1_PARTITION1.getPostalCode(), + new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity())); + + final List
result = TestUtils.toList(repository.findAll()); + assertThat(result.size()).isEqualTo(3); + + addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(), + new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity())); + + assertThat(addressById.isPresent()).isFalse(); + } + + @Test + public void testFindAllByPartitionKey() { + List
findAll = + repository.findAll(new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity())); + // Since there are two addresses with partition1 + assertThat(findAll.size()).isEqualTo(2); + assertThat(findAll.containsAll(Lists.newArrayList(TEST_ADDRESS1_PARTITION1, + TEST_ADDRESS2_PARTITION1))).isTrue(); + + findAll = repository.findAll(new PartitionKey(TEST_ADDRESS1_PARTITION2.getCity())); + // Since there is one address with partition2 + assertThat(findAll.size()).isEqualTo(1); + assertThat(findAll.contains(TEST_ADDRESS1_PARTITION2)).isTrue(); + + + findAll = repository.findAll(new PartitionKey(TEST_ADDRESS4_PARTITION3.getCity())); + // Since there is one address with partition3 + assertThat(findAll.size()).isEqualTo(1); + assertThat(findAll.contains(TEST_ADDRESS4_PARTITION3)).isTrue(); + } + + @Test + public void testUpdateEntity() { + final Address updatedAddress = new Address(TEST_ADDRESS1_PARTITION1.getPostalCode(), TestConstants.NEW_STREET, + TEST_ADDRESS1_PARTITION1.getCity()); + + repository.save(updatedAddress); + + final List
results = + repository.findByPostalCodeAndCity(updatedAddress.getPostalCode(), updatedAddress.getCity()); + + assertThat(results.size()).isEqualTo(1); + assertThat(results.get(0).getStreet()).isEqualTo(updatedAddress.getStreet()); + assertThat(results.get(0).getPostalCode()).isEqualTo(updatedAddress.getPostalCode()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java new file mode 100644 index 000000000000..ca4368e987c0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Contact; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.ContactRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ContactRepositoryIT { + + private static final Contact TEST_CONTACT = new Contact("testId", "faketitle"); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Contact.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + ContactRepository repository; + + @Autowired + private CosmosTemplate template; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + repository.save(TEST_CONTACT); + isSetupDone = true; + } + + @After + public void cleanup() { + repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAll() { + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId()); + assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle()); + + final Contact contact = repository.findById(TEST_CONTACT.getLogicId()).get(); + + assertThat(contact.getLogicId()).isEqualTo(TEST_CONTACT.getLogicId()); + assertThat(contact.getTitle()).isEqualTo(TEST_CONTACT.getTitle()); + } + + @Test + public void testCountAndDeleteByID() { + final Contact contact2 = new Contact("newid", "newtitle"); + repository.save(contact2); + final List all = TestUtils.toList(repository.findAll()); + assertThat(all.size()).isEqualTo(2); + + long count = repository.count(); + assertThat(count).isEqualTo(2); + + repository.deleteById(contact2.getLogicId()); + + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId()); + assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle()); + + count = repository.count(); + assertThat(count).isEqualTo(1); + } + + @Test + public void testCountAndDeleteEntity() { + final Contact contact2 = new Contact("newid", "newtitle"); + repository.save(contact2); + final List all = TestUtils.toList(repository.findAll()); + assertThat(all.size()).isEqualTo(2); + + repository.delete(contact2); + + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId()); + assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle()); + } + + @Test + public void testUpdateEntity() { + final Contact updatedContact = new Contact(TEST_CONTACT.getLogicId(), "updated"); + + final Contact savedContact = repository.save(updatedContact); + + // Test save operation return saved entity + assertThat(savedContact.getLogicId()).isEqualTo(updatedContact.getLogicId()); + assertThat(savedContact.getTitle()).isEqualTo(updatedContact.getTitle()); + + final Contact contact = repository.findById(TEST_CONTACT.getLogicId()).get(); + + assertThat(contact.getLogicId()).isEqualTo(updatedContact.getLogicId()); + assertThat(contact.getTitle()).isEqualTo(updatedContact.getTitle()); + } + + @Test + public void testBatchOperations() { + + final Contact contact1 = new Contact("newid1", "newtitle"); + final Contact contact2 = new Contact("newid2", "newtitle"); + final ArrayList contacts = new ArrayList(); + contacts.add(contact1); + contacts.add(contact2); + final Iterable savedContacts = repository.saveAll(contacts); + + final AtomicInteger savedCount = new AtomicInteger(); + savedContacts.forEach(se -> { + savedCount.incrementAndGet(); + assertThat(contacts.contains(se)).isTrue(); + }); + + assertThat(savedCount.get()).isEqualTo(contacts.size()); + + final ArrayList ids = new ArrayList(); + ids.add(contact1.getLogicId()); + ids.add(contact2.getLogicId()); + final List result = Lists.newArrayList(repository.findAllById(ids)); + + assertThat(result.size()).isEqualTo(2); + + repository.deleteAll(contacts); + + final List result2 = Lists.newArrayList(repository.findAllById(ids)); + assertThat(result2.size()).isEqualTo(0); + } + + @Test + public void testCustomQuery() { + final List result = repository.findByTitle(TEST_CONTACT.getTitle()); + + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getLogicId()).isEqualTo(TEST_CONTACT.getLogicId()); + assertThat(result.get(0).getTitle()).isEqualTo(TEST_CONTACT.getTitle()); + + } + + @Test + @Ignore // TODO(kuthapar): v3 doesn't support creation of items without id. + public void testNullIdContact() { + final Contact nullIdContact = new Contact(null, "testTitile"); + final Contact savedContact = repository.save(nullIdContact); + + Assert.assertNotNull(savedContact.getLogicId()); + Assert.assertEquals(nullIdContact.getTitle(), savedContact.getTitle()); + } + + @Test + public void testFindById() { + final Optional optional = repository.findById(TEST_CONTACT.getLogicId()); + + Assert.assertTrue(optional.isPresent()); + Assert.assertEquals(TEST_CONTACT, optional.get()); + Assert.assertFalse(repository.findById("").isPresent()); + } + + @Test + public void testFindByIdNotFound() { + final Optional optional = repository.findById("unknown-id"); + + Assert.assertFalse(optional.isPresent()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java new file mode 100644 index 000000000000..943dfe2072bc --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.IndexingPolicy; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.domain.Role; +import com.microsoft.azure.spring.data.cosmosdb.domain.TimeToLiveSample; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.Assert; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class CosmosAnnotationIT { + private static final Role TEST_ROLE = new Role(TestConstants.ID_1, TestConstants.LEVEL, + TestConstants.ROLE_NAME); + + @Autowired + private ApplicationContext applicationContext; + @Autowired + private CosmosDBConfig dbConfig; + + private static CosmosTemplate cosmosTemplate; + private static CosmosContainerProperties collectionRole; + private static CosmosContainerProperties collectionSample; + private static CosmosEntityInformation roleInfo; + private static CosmosEntityInformation sampleInfo; + + private static boolean initialized; + + @Before + public void setUp() throws ClassNotFoundException { + if (!initialized) { + final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); + + roleInfo = new CosmosEntityInformation<>(Role.class); + sampleInfo = new CosmosEntityInformation<>(TimeToLiveSample.class); + final CosmosMappingContext dbContext = new CosmosMappingContext(); + + dbContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final MappingCosmosConverter mappingConverter = new MappingCosmosConverter(dbContext, null); + + cosmosTemplate = new CosmosTemplate(cosmosDbFactory, mappingConverter, dbConfig.getDatabase()); + initialized = true; + } + collectionRole = cosmosTemplate.createContainerIfNotExists(roleInfo); + + collectionSample = cosmosTemplate.createContainerIfNotExists(sampleInfo); + + cosmosTemplate.insert(roleInfo.getContainerName(), TEST_ROLE, null); + } + + @AfterClass + public static void afterClassCleanup() { + cosmosTemplate.deleteContainer(roleInfo.getContainerName()); + cosmosTemplate.deleteContainer(sampleInfo.getContainerName()); + } + + @Test + public void testTimeToLiveAnnotation() { + Integer timeToLive = sampleInfo.getTimeToLive(); + assertThat(timeToLive).isEqualTo(collectionSample.defaultTimeToLive()); + + timeToLive = roleInfo.getTimeToLive(); + assertThat(timeToLive).isEqualTo(collectionRole.defaultTimeToLive()); + } + + @Test + @Ignore // TODO(kuthapar): Ignore this test case for now, will update this from service update. + public void testIndexingPolicyAnnotation() { + final IndexingPolicy policy = collectionRole.indexingPolicy(); + + Assert.isTrue(policy.indexingMode() == TestConstants.INDEXINGPOLICY_MODE, + "unmatched collection policy indexing mode of class Role"); + Assert.isTrue(policy.automatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC, + "unmatched collection policy automatic of class Role"); + + TestUtils.testIndexingPolicyPathsEquals(policy.includedPaths(), TestConstants.INCLUDEDPATHS); + TestUtils.testIndexingPolicyPathsEquals(policy.excludedPaths(), TestConstants.EXCLUDEDPATHS); + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java new file mode 100644 index 000000000000..c476c4a57d0e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Customer; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.CustomerRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class CustomerRepositoryIT { + + private static final String USER_NAME_0 = "username-0"; + private static final String USER_NAME_1 = "username-1"; + private static final String FAKE_USER_NAME = "username-fake"; + + private static final Long USER_AGE_0 = 34L; + private static final Long USER_AGE_1 = 45L; + + private static final String CUSTOMER_ID_0 = "id-0"; + private static final String CUSTOMER_ID_1 = "id-1"; + private static final String CUSTOMER_ID_2 = "id-2"; + + private static final Long CUSTOMER_LEVEL_0 = 1L; + private static final Long CUSTOMER_LEVEL_1 = 2L; + + private static final Customer.User USER_0 = new Customer.User(USER_NAME_0, USER_AGE_0); + private static final Customer.User USER_1 = new Customer.User(USER_NAME_1, USER_AGE_1); + private static final Customer.User USER_2 = new Customer.User(USER_NAME_0, USER_AGE_1); + + private static final Customer CUSTOMER_0 = new Customer(CUSTOMER_ID_0, CUSTOMER_LEVEL_0, USER_0); + private static final Customer CUSTOMER_1 = new Customer(CUSTOMER_ID_1, CUSTOMER_LEVEL_1, USER_1); + private static final Customer CUSTOMER_2 = new Customer(CUSTOMER_ID_2, CUSTOMER_LEVEL_1, USER_2); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Customer.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CustomerRepository repository; + + @Autowired + private CosmosTemplate template; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.saveAll(Arrays.asList(CUSTOMER_0, CUSTOMER_1, CUSTOMER_2)); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + private void assertCustomerListEquals(@NonNull List customers, @NonNull List reference) { + Assert.assertEquals(reference.size(), customers.size()); + + customers.sort(Comparator.comparing(Customer::getId)); + reference.sort(Comparator.comparing(Customer::getId)); + + Assert.assertEquals(reference, customers); + } + + @Test + public void testFindByUserAndLevel() { + final List references = Arrays.asList(CUSTOMER_0, CUSTOMER_2); + List customers = this.repository.findByUser_Name(USER_NAME_0); + + assertCustomerListEquals(references, customers); + + customers = this.repository.findByUser_Name(FAKE_USER_NAME); + + Assert.assertTrue(customers.isEmpty()); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java new file mode 100644 index 000000000000..3638f31c8b90 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.domain.IntegerIdDomain; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.IntegerIdDomainRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class IntegerIdDomainRepositoryIT { + + private static final Integer ID = 231234; + private static final String NAME = "panli"; + private static final IntegerIdDomain DOMAIN = new IntegerIdDomain(ID, NAME); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(IntegerIdDomain.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private IntegerIdDomainRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.save(DOMAIN); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testIntegerIdDomain() { + this.repository.deleteAll(); + Assert.assertFalse(this.repository.findById(ID).isPresent()); + + this.repository.save(DOMAIN); + final Optional foundOptional = this.repository.findById(ID); + + Assert.assertTrue(foundOptional.isPresent()); + Assert.assertEquals(DOMAIN.getNumber(), foundOptional.get().getNumber()); + Assert.assertEquals(DOMAIN.getName(), foundOptional.get().getName()); + + this.repository.delete(DOMAIN); + + Assert.assertFalse(this.repository.findById(ID).isPresent()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidDomain() { + new CosmosEntityInformation(InvalidDomain.class); + } + + @Test + public void testBasicQuery() { + final IntegerIdDomain save = this.repository.save(DOMAIN); + Assert.assertNotNull(save); + } + + @Test + public void testSaveAndFindById() { + Assert.assertNotNull(this.repository.save(DOMAIN)); + + final Optional savedEntity = this.repository.findById(DOMAIN.getNumber()); + Assert.assertTrue(savedEntity.isPresent()); + Assert.assertEquals(DOMAIN, savedEntity.get()); + } + + @Test + public void testSaveAllAndFindAll() { + Assert.assertTrue(this.repository.findAll().iterator().hasNext()); + + final Set entitiesToSave = Collections.singleton(DOMAIN); + this.repository.saveAll(entitiesToSave); + + final Set savedEntities = StreamSupport.stream(this.repository.findAll().spliterator(), false) + .collect(Collectors.toSet()); + + Assert.assertTrue(entitiesToSave.containsAll(savedEntities)); + } + + @Test + @Ignore // TODO(kuthapar): findById IN clause not working in case of Integer + public void testFindAllById() { + final Iterable allById = + this.repository.findAllById(Collections.singleton(DOMAIN.getNumber())); + Assert.assertTrue(allById.iterator().hasNext()); + } + + @Test + public void testCount() { + Assert.assertEquals(1, repository.count()); + } + + @Test + public void testDeleteById() { + this.repository.save(DOMAIN); + this.repository.deleteById(DOMAIN.getNumber()); + Assert.assertEquals(0, this.repository.count()); + } + + @Test(expected = CosmosDBAccessException.class) + public void testDeleteByIdShouldFailIfNothingToDelete() { + this.repository.deleteAll(); + this.repository.deleteById(DOMAIN.getNumber()); + } + + @Test + public void testDelete() { + this.repository.save(DOMAIN); + this.repository.delete(DOMAIN); + Assert.assertEquals(0, this.repository.count()); + } + + @Test(expected = CosmosDBAccessException.class) + public void testDeleteShouldFailIfNothingToDelete() { + this.repository.deleteAll(); + this.repository.delete(DOMAIN); + } + + @Test + public void testDeleteAll() { + this.repository.save(DOMAIN); + this.repository.deleteAll(Collections.singleton(DOMAIN)); + Assert.assertEquals(0, this.repository.count()); + } + + @Test + public void testExistsById() { + this.repository.save(DOMAIN); + Assert.assertTrue(this.repository.existsById(DOMAIN.getNumber())); + } + + @Test + public void testFindAllSort() { + final IntegerIdDomain other = new IntegerIdDomain(DOMAIN.getNumber() + 1, "other-name"); + this.repository.save(other); + this.repository.save(DOMAIN); + + final Sort ascSort = Sort.by(Sort.Direction.ASC, "number"); + final List ascending = StreamSupport + .stream(this.repository.findAll(ascSort).spliterator(), false) + .collect(Collectors.toList()); + Assert.assertEquals(2, ascending.size()); + Assert.assertEquals(DOMAIN, ascending.get(0)); + Assert.assertEquals(other, ascending.get(1)); + + final Sort descSort = Sort.by(Sort.Direction.DESC, "number"); + final List descending = StreamSupport + .stream(this.repository.findAll(descSort).spliterator(), false) + .collect(Collectors.toList()); + Assert.assertEquals(2, descending.size()); + Assert.assertEquals(other, descending.get(0)); + Assert.assertEquals(DOMAIN, descending.get(1)); + + } + + @Test + public void testFindAllPageable() { + final IntegerIdDomain other = new IntegerIdDomain(DOMAIN.getNumber() + 1, "other-name"); + this.repository.save(DOMAIN); + this.repository.save(other); + + final Page page1 = this.repository.findAll(new CosmosPageRequest(0, 1, null)); + final Iterator page1Iterator = page1.iterator(); + Assert.assertTrue(page1Iterator.hasNext()); + Assert.assertEquals(DOMAIN, page1Iterator.next()); + + final Page page2 = this.repository.findAll(new CosmosPageRequest(1, 1, null)); + final Iterator page2Iterator = page2.iterator(); + Assert.assertTrue(page2Iterator.hasNext()); + Assert.assertEquals(DOMAIN, page2Iterator.next()); + } + + private static class InvalidDomain { + + private int count; + + private String location; + + public InvalidDomain(int count, String location) { + this.count = count; + this.location = location; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvalidDomain that = (InvalidDomain) o; + return count == that.count && + Objects.equals(location, that.location); + } + + @Override + public int hashCode() { + return Objects.hash(count, location); + } + + @Override + public String toString() { + return "InvalidDomain{" + + "count=" + count + + ", location='" + location + '\'' + + '}'; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java new file mode 100644 index 000000000000..4fa4053db39b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java @@ -0,0 +1,262 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Importance; +import com.microsoft.azure.spring.data.cosmosdb.domain.Memo; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.MemoRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class MemoRepositoryIT { + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(TestConstants.DATE_FORMAT); + + private static Date memoDate; + private static Date memoDateBefore; + private static Date memoDateAfter; + private static Date futureDate1; + private static Date futureDate2; + + private static Memo testMemo1; + private static Memo testMemo2; + private static Memo testMemo3; + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Memo.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + MemoRepository repository; + + @BeforeClass + public static void init() throws ParseException { + memoDate = DATE_FORMAT.parse(TestConstants.DATE_STRING); + memoDateBefore = DATE_FORMAT.parse(TestConstants.DATE_BEFORE_STRING); + memoDateAfter = DATE_FORMAT.parse(TestConstants.DATE_AFTER_STRING); + futureDate1 = DATE_FORMAT.parse(TestConstants.DATE_FUTURE_STRING_1); + futureDate2 = DATE_FORMAT.parse(TestConstants.DATE_FUTURE_STRING_2); + testMemo1 = new Memo(TestConstants.ID_1, TestConstants.MESSAGE, memoDateBefore, Importance.HIGH); + testMemo2 = new Memo(TestConstants.ID_2, TestConstants.NEW_MESSAGE, memoDate, Importance.LOW); + testMemo3 = new Memo(TestConstants.ID_3, TestConstants.NEW_MESSAGE, memoDateAfter, Importance.LOW); + } + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + repository.saveAll(Arrays.asList(testMemo1, testMemo2, testMemo3)); + isSetupDone = true; + } + + @After + public void cleanup() { + repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAll() { + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(3); + } + + @Test + public void testFindByDate() { + final List result = repository.findMemoByDate(memoDate); + + assertThat(result.size()).isEqualTo(1); + assertMemoEquals(result.get(0), testMemo1); + } + + @Test + public void testFindByEnum() { + final List result = repository.findMemoByImportance(testMemo1.getImportance()); + + assertThat(result.size()).isEqualTo(1); + assertMemoEquals(result.get(0), testMemo1); + } + + private void assertMemoEquals(Memo actual, Memo expected) { + assertThat(actual.getId().equals(expected.getId())); + assertThat(actual.getMessage().equals(expected.getMessage())); + assertThat(actual.getDate().equals(expected.getDate())); + assertThat(actual.getImportance().equals(expected.getImportance())); + } + + @Test + public void testFindByBefore() { + List memos = this.repository.findByDateBefore(memoDateBefore); + + Assert.assertTrue(memos.isEmpty()); + + memos = this.repository.findByDateBefore(memoDate); + + Assert.assertEquals(1, memos.size()); + Assert.assertEquals(testMemo1, memos.get(0)); + + memos = this.repository.findByDateBefore(memoDateAfter); + final List reference = Arrays.asList(testMemo1, testMemo2); + + memos.sort(Comparator.comparing(Memo::getId)); + reference.sort(Comparator.comparing(Memo::getId)); + + Assert.assertEquals(reference.size(), memos.size()); + Assert.assertEquals(reference, memos); + } + + @Test + public void testFindByBeforeWithAndOr() { + List memos = this.repository.findByDateBeforeAndMessage(memoDate, TestConstants.NEW_MESSAGE); + + Assert.assertTrue(memos.isEmpty()); + + memos = this.repository.findByDateBeforeAndMessage(memoDate, TestConstants.MESSAGE); + + Assert.assertEquals(1, memos.size()); + Assert.assertEquals(testMemo1, memos.get(0)); + + memos = this.repository.findByDateBeforeOrMessage(memoDateAfter, TestConstants.MESSAGE); + final List reference = Arrays.asList(testMemo1, testMemo2); + + memos.sort(Comparator.comparing(Memo::getId)); + reference.sort(Comparator.comparing(Memo::getId)); + + Assert.assertEquals(reference.size(), memos.size()); + Assert.assertEquals(reference, memos); + } + + @Test + public void testFindByAfter() { + List memos = this.repository.findByDateAfter(memoDateAfter); + + Assert.assertTrue(memos.isEmpty()); + + memos = this.repository.findByDateAfter(memoDate); + + Assert.assertEquals(1, memos.size()); + Assert.assertEquals(testMemo3, memos.get(0)); + + memos = this.repository.findByDateAfter(memoDateBefore); + final List reference = Arrays.asList(testMemo2, testMemo3); + + memos.sort(Comparator.comparing(Memo::getId)); + reference.sort(Comparator.comparing(Memo::getId)); + + Assert.assertEquals(reference.size(), memos.size()); + Assert.assertEquals(reference, memos); + } + + @Test + public void testFindByAfterWithAndOr() { + List memos = this.repository.findByDateAfterAndMessage(memoDate, TestConstants.MESSAGE); + + Assert.assertTrue(memos.isEmpty()); + + memos = this.repository.findByDateAfterAndMessage(memoDate, TestConstants.NEW_MESSAGE); + + Assert.assertEquals(1, memos.size()); + Assert.assertEquals(testMemo3, memos.get(0)); + + memos = this.repository.findByDateAfterOrMessage(memoDateBefore, TestConstants.MESSAGE); + final List reference = Arrays.asList(testMemo1, testMemo2, testMemo3); + + memos.sort(Comparator.comparing(Memo::getId)); + reference.sort(Comparator.comparing(Memo::getId)); + + Assert.assertEquals(reference.size(), memos.size()); + Assert.assertEquals(reference, memos); + } + + @Test + public void testFindByBetween() { + List memos = this.repository + .findByDateBetween(testMemo1.getDate(), testMemo3.getDate()); + List reference = Arrays.asList(testMemo1, testMemo2, testMemo3); + + assertMemoListEquals(memos, reference); + + memos = this.repository.findByDateBetween(testMemo1.getDate(), testMemo2.getDate()); + reference = Arrays.asList(testMemo1, testMemo2); + + assertMemoListEquals(memos, reference); + + memos = this.repository.findByDateBetween(futureDate1, futureDate2); + reference = Arrays.asList(); + + assertMemoListEquals(memos, reference); + } + + @Test + public void testFindByBetweenWithAnd() { + final List memos = this.repository + .findByDateBetweenAndMessage(testMemo1.getDate(), testMemo2.getDate(), TestConstants.MESSAGE); + assertMemoListEquals(memos, Arrays.asList(testMemo1)); + } + + @Test + public void testFindByBetweenWithOr() { + final List memos = this.repository + .findByDateBetweenOrMessage(testMemo1.getDate(), testMemo2.getDate(), TestConstants.NEW_MESSAGE); + assertMemoListEquals(memos, Arrays.asList(testMemo1, testMemo2, testMemo3)); + } + + private void assertMemoListEquals(List memos, List reference) { + memos.sort(Comparator.comparing(Memo::getId)); + reference.sort(Comparator.comparing(Memo::getId)); + + Assert.assertEquals(reference.size(), memos.size()); + Assert.assertEquals(reference, memos); + } + + @Test(expected = CosmosDBAccessException.class) + @Ignore // TODO(pan): Ignore this test case for now, will update this from service update. + public void testFindByStartsWithWithException() { + repository.findByMessageStartsWith(testMemo1.getMessage()); + } + + @Test + public void testFindByStartsWith() { + final List result = repository.findByMessageStartsWith(testMemo1.getMessage().substring(0, 10)); + Assert.assertEquals(testMemo1, result.get(0)); + Assert.assertEquals(1, result.size()); + } + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java new file mode 100644 index 000000000000..7e1d9a984a34 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.FeedResponse; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.domain.PageableAddress; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.PageableAddressRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.domain.Page; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +import java.util.ArrayList; +import java.util.List; + +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateNonLastPage; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PAGE_SIZE_1; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.PAGE_SIZE_3; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class PageableAddressRepositoryIT { + private static final PageableAddress TEST_ADDRESS1_PARTITION1 = new PageableAddress( + TestConstants.POSTAL_CODE, TestConstants.STREET, TestConstants.CITY); + private static final PageableAddress TEST_ADDRESS2_PARTITION1 = new PageableAddress( + TestConstants.POSTAL_CODE_0, TestConstants.STREET, TestConstants.CITY); + private static final PageableAddress TEST_ADDRESS1_PARTITION2 = new PageableAddress( + TestConstants.POSTAL_CODE_1, TestConstants.STREET_0, TestConstants.CITY_0); + private static final PageableAddress TEST_ADDRESS4_PARTITION3 = new PageableAddress( + TestConstants.POSTAL_CODE, TestConstants.STREET_1, TestConstants.CITY_1); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(PageableAddress.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private PageableAddressRepository repository; + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private CosmosDBConfig dbConfig; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + repository.save(TEST_ADDRESS1_PARTITION1); + repository.save(TEST_ADDRESS1_PARTITION2); + repository.save(TEST_ADDRESS2_PARTITION1); + repository.save(TEST_ADDRESS4_PARTITION3); + isSetupDone = true; + } + + @After + public void cleanup() { + repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAll() { + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(4); + } + + @Test + public void testFindAllByPage() { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_3, null); + final Page page = repository.findAll(pageRequest); + + assertThat(page.getContent().size()).isLessThanOrEqualTo(PAGE_SIZE_3); + validateNonLastPage(page, PAGE_SIZE_3); + + final Page nextPage = repository.findAll(page.getPageable()); + assertThat(nextPage.getContent().size()).isLessThanOrEqualTo(PAGE_SIZE_3); + validateLastPage(nextPage, nextPage.getContent().size()); + } + + @Test + public void testFindWithPartitionKeySinglePage() { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_3, null); + final Page page = repository.findByCity(TestConstants.CITY, pageRequest); + + assertThat(page.getContent().size()).isEqualTo(2); + validateResultCityMatch(page, TestConstants.CITY); + validateLastPage(page, page.getContent().size()); + } + + @Test + public void testFindWithPartitionKeyMultiPages() { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null); + final Page page = repository.findByCity(TestConstants.CITY, pageRequest); + + assertThat(page.getContent().size()).isEqualTo(PAGE_SIZE_1); + validateResultCityMatch(page, TestConstants.CITY); + validateNonLastPage(page, PAGE_SIZE_1); + + final Page nextPage = repository.findByCity(TestConstants.CITY, page.getPageable()); + + assertThat(nextPage.getContent().size()).isEqualTo(PAGE_SIZE_1); + validateResultCityMatch(page, TestConstants.CITY); + validateLastPage(nextPage, PAGE_SIZE_1); + } + + @Test + public void testFindWithoutPartitionKeySinglePage() { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_3, null); + final Page page = repository.findByStreet(TestConstants.STREET, pageRequest); + + assertThat(page.getContent().size()).isEqualTo(2); + validateResultStreetMatch(page, TestConstants.STREET); + validateLastPage(page, page.getContent().size()); + } + + @Test + public void testFindWithoutPartitionKeyMultiPages() { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null); + final Page page = repository.findByStreet(TestConstants.STREET, pageRequest); + + assertThat(page.getContent().size()).isEqualTo(1); + validateResultStreetMatch(page, TestConstants.STREET); + validateNonLastPage(page, PAGE_SIZE_1); + + final Page nextPage = repository.findByStreet(TestConstants.STREET, page.getPageable()); + + assertThat(nextPage.getContent().size()).isEqualTo(PAGE_SIZE_1); + validateResultStreetMatch(page, TestConstants.STREET); + validateLastPage(nextPage, PAGE_SIZE_1); + } + + @Test + public void testOffsetAndLimit() { + final int skipCount = 2; + final int takeCount = 2; + final List results = new ArrayList<>(); + final FeedOptions options = new FeedOptions(); + options.enableCrossPartitionQuery(true); + options.maxDegreeOfParallelism(2); + + final String query = "SELECT * from c OFFSET " + skipCount + " LIMIT " + takeCount; + + final CosmosClient cosmosClient = applicationContext.getBean(CosmosClient.class); + final Flux> feedResponseFlux = + cosmosClient.getDatabase(dbConfig.getDatabase()) + .getContainer(entityInformation.getContainerName()) + .queryItems(query, options); + + StepVerifier.create(feedResponseFlux) + .consumeNextWith(cosmosItemPropertiesFeedResponse -> + results.addAll(cosmosItemPropertiesFeedResponse.results())) + .verifyComplete(); + assertThat(results.size()).isEqualTo(takeCount); + } + + private void validateResultCityMatch(Page page, String city) { + assertThat((int) page.getContent() + .stream() + .filter(address -> address.getCity().equals(city)) + .count()).isEqualTo(page.getContent().size()); + } + + private void validateResultStreetMatch(Page page, String street) { + assertThat((int) page.getContent() + .stream() + .filter(address -> address.getStreet().equals(street)) + .count()).isEqualTo(page.getContent().size()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java new file mode 100644 index 000000000000..35e4a60ee519 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.FeedResponse; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.domain.Importance; +import com.microsoft.azure.spring.data.cosmosdb.domain.PageableMemo; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.PageableMemoRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class PageableMemoRepositoryIT { + + private static final int TOTAL_CONTENT_SIZE = 500; + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(PageableMemo.class); + + private static CosmosTemplate staticTemplate; + + @Autowired + private CosmosTemplate template; + + @Autowired + private PageableMemoRepository repository; + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private CosmosDBConfig dbConfig; + + private static Set memoSet; + + private static boolean isSetupDone; + + @Before + public void setUp() { + if (isSetupDone) { + return; + } + template.createContainerIfNotExists(entityInformation); + staticTemplate = template; + memoSet = new HashSet<>(); + final Random random = new Random(); + final Importance[] importanceValues = Importance.values(); + + // Create larger documents with size more than 10 kb + for (int i = 0; i < TOTAL_CONTENT_SIZE; i++) { + final String id = UUID.randomUUID().toString(); + final String message = UUID.randomUUID().toString(); + final int randomIndex = random.nextInt(3); + final PageableMemo memo = new PageableMemo(id, message, new Date(), importanceValues[randomIndex]); + repository.save(memo); + memoSet.add(memo); + } + isSetupDone = true; + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAllWithPageSizeLessThanReturned() { + final Set memos = findAllWithPageSize(20); + assertThat(memos).isEqualTo(memoSet); + } + + @Test + public void testFindAllWithPageSizeLessThanTotal() { + final Set memos = findAllWithPageSize(200); + assertThat(memos).isEqualTo(memoSet); + } + + @Test + public void testFindAllWithPageSizeGreaterThanTotal() { + final Set memos = findAllWithPageSize(10000); + assertThat(memos).isEqualTo(memoSet); + } + + @Test + public void testOffsetAndLimitLessThanTotal() { + final int skipCount = 50; + final int takeCount = 200; + verifyItemsWithOffsetAndLimit(skipCount, takeCount, takeCount); + } + + @Test + public void testOffsetAndLimitEqualToTotal() { + final int skipCount = 100; + final int takeCount = 300; + verifyItemsWithOffsetAndLimit(skipCount, takeCount, takeCount); + } + + + @Test + public void testOffsetAndLimitGreaterThanTotal() { + final int skipCount = 300; + final int takeCount = 300; + verifyItemsWithOffsetAndLimit(skipCount, takeCount, TOTAL_CONTENT_SIZE - skipCount); + } + + private Flux> getItemsWithOffsetAndLimit(int skipCount, int takeCount) { + final FeedOptions options = new FeedOptions(); + options.enableCrossPartitionQuery(true); + options.maxDegreeOfParallelism(2); + + final String query = "SELECT * from c OFFSET " + skipCount + " LIMIT " + takeCount; + + final CosmosClient cosmosClient = applicationContext.getBean(CosmosClient.class); + return cosmosClient.getDatabase(dbConfig.getDatabase()) + .getContainer(entityInformation.getContainerName()) + .queryItems(query, options); + } + + private void verifyItemsWithOffsetAndLimit(int skipCount, int takeCount, int verifyCount) { + final List itemsWithOffsetAndLimit = new ArrayList<>(); + final Flux> itemsWithOffsetAndLimitFlux = + getItemsWithOffsetAndLimit(skipCount, takeCount); + StepVerifier.create(itemsWithOffsetAndLimitFlux) + .thenConsumeWhile(cosmosItemPropertiesFeedResponse -> { + itemsWithOffsetAndLimit.addAll(cosmosItemPropertiesFeedResponse.results()); + return true; + }) + .verifyComplete(); + assertThat(itemsWithOffsetAndLimit.size()).isEqualTo(verifyCount); + } + + private Set findAllWithPageSize(int pageSize) { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null); + Page page = repository.findAll(pageRequest); + final Set outputSet = new HashSet<>(page.getContent()); + while (page.hasNext()) { + final Pageable pageable = page.nextPageable(); + page = repository.findAll(pageable); + outputSet.addAll((page.getContent())); + } + return outputSet; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java new file mode 100644 index 000000000000..bea46dbc742e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.domain.PageablePerson; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.PageablePersonRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class PageablePersonRepositoryIT { + + private static final int TOTAL_CONTENT_SIZE = 50; + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(PageablePerson.class); + + private static CosmosTemplate staticTemplate; + + @Autowired + private CosmosTemplate template; + + @Autowired + private PageablePersonRepository repository; + + private static Set personSet; + + private static boolean isSetupDone; + + @Before + public void setUp() { + if (isSetupDone) { + return; + } + personSet = new HashSet<>(); + template.createContainerIfNotExists(entityInformation); + staticTemplate = template; + + // Create larger documents with size more than 10 kb + for (int i = 0; i < TOTAL_CONTENT_SIZE; i++) { + final List hobbies = new ArrayList<>(); + hobbies.add(StringUtils.repeat("hobbies-" + UUID.randomUUID().toString(), + (int) FileUtils.ONE_KB * 10)); + final List
address = new ArrayList<>(); + address.add(new Address("postalCode-" + UUID.randomUUID().toString(), + "street-" + UUID.randomUUID().toString(), + "city-" + UUID.randomUUID().toString())); + final PageablePerson person = new PageablePerson(UUID.randomUUID().toString(), + UUID.randomUUID().toString(), UUID.randomUUID().toString(), + hobbies, address); + repository.save(person); + personSet.add(person); + } + isSetupDone = true; + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + // Cosmos DB can return any number of documents less than or equal to requested page size + // Because of available RUs, the number of return documents vary. + // With documents more than 10 KB, and collection RUs 400, + // it usually return documents less than total content size. + + // This test covers the case where page size is greater than returned documents + @Test + public void testFindAllWithPageSizeGreaterThanReturned() { + final Set outputSet = findAllWithPageSize(30, false); + assertThat(outputSet).isEqualTo(personSet); + } + + // This test covers the case where page size is less than returned documents + @Test + public void testFindAllWithPageSizeLessThanReturned() { + final Set outputSet = findAllWithPageSize(5, false); + assertThat(outputSet).isEqualTo(personSet); + } + + // This test covers the case where page size is greater than total number of documents + @Test + public void testFindAllWithPageSizeGreaterThanTotal() { + final Set outputSet = findAllWithPageSize(120, true); + assertThat(outputSet).isEqualTo(personSet); + } + + private Set findAllWithPageSize(int pageSize, boolean checkContentLimit) { + final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null); + Page page = repository.findAll(pageRequest); + final Set outputSet = new HashSet<>(page.getContent()); + if (checkContentLimit) { + // Make sure CosmosDB returns less number of documents than requested + // This will verify the functionality of new pagination implementation + assertThat(page.getContent().size()).isLessThan(pageSize); + } + while (page.hasNext()) { + final Pageable pageable = page.nextPageable(); + page = repository.findAll(pageable); + outputSet.addAll((page.getContent())); + } + return outputSet; + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java new file mode 100644 index 000000000000..1ffa71649534 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +public class PersonRepositoryIT { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java new file mode 100644 index 000000000000..1e0475d9257d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java @@ -0,0 +1,526 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.PartitionKey; +import com.google.common.collect.Lists; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Project; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.ProjectRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ProjectRepositoryIT { + + private static final String ID_0 = "id-0"; + private static final String ID_1 = "id-1"; + private static final String ID_2 = "id-2"; + private static final String ID_3 = "id-3"; + private static final String ID_4 = "id-4"; + + private static final String NAME_0 = "name-0"; + private static final String NAME_1 = "name-1"; + private static final String NAME_2 = "name-2"; + private static final String NAME_3 = "name-3"; + private static final String FAKE_NAME = "fake-name"; + + private static final String CREATOR_0 = "creator-0"; + private static final String CREATOR_1 = "creator-1"; + private static final String CREATOR_2 = "creator-2"; + private static final String CREATOR_3 = "creator-3"; + private static final String FAKE_CREATOR = "fake-creator"; + + private static final Long STAR_COUNT_MIN = -1L; + private static final Long STAR_COUNT_0 = 0L; + private static final Long STAR_COUNT_1 = 1L; + private static final Long STAR_COUNT_2 = 2L; + private static final Long STAR_COUNT_3 = 3L; + private static final Long STAR_COUNT_MAX = 100L; + + private static final Long FORK_COUNT_0 = 0L; + private static final Long FORK_COUNT_1 = 1L; + private static final Long FORK_COUNT_2 = 2L; + private static final Long FORK_COUNT_3 = 3L; + private static final Long FAKE_COUNT = 123234L; + private static final Long FORK_COUNT_MAX = 100L; + + private static final Project PROJECT_0 = new Project(ID_0, NAME_0, CREATOR_0, true, STAR_COUNT_0, FORK_COUNT_0); + private static final Project PROJECT_1 = new Project(ID_1, NAME_1, CREATOR_1, true, STAR_COUNT_1, FORK_COUNT_1); + private static final Project PROJECT_2 = new Project(ID_2, NAME_2, CREATOR_2, true, STAR_COUNT_2, FORK_COUNT_2); + private static final Project PROJECT_3 = new Project(ID_3, NAME_3, CREATOR_3, true, STAR_COUNT_3, FORK_COUNT_3); + private static final Project PROJECT_4 = new Project(ID_4, NAME_0, CREATOR_0, false, STAR_COUNT_0, FORK_COUNT_0); + + private static final List PROJECTS = Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_3, PROJECT_4); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Project.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private ProjectRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.saveAll(PROJECTS); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + private void assertProjectListEquals(@NonNull List projects, @NonNull List reference) { + Assert.assertEquals(reference.size(), projects.size()); + + projects.sort(Comparator.comparing(Project::getId)); + reference.sort(Comparator.comparing(Project::getId)); + + Assert.assertEquals(reference, projects); + } + + @Test + public void testFindByWithAnd() { + List projects = this.repository.findByNameAndStarCount(NAME_1, STAR_COUNT_1); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_1)); + + projects = this.repository.findByNameAndStarCount(NAME_0, STAR_COUNT_1); + + Assert.assertTrue(projects.isEmpty()); + + projects = this.repository.findByNameAndStarCount(NAME_0, STAR_COUNT_0); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + } + + @Test + public void testFindByWithOr() { + List projects = this.repository.findByNameOrForkCount(NAME_2, STAR_COUNT_2); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_2)); + + projects = this.repository.findByNameOrForkCount(FAKE_NAME, FAKE_COUNT); + + Assert.assertTrue(projects.isEmpty()); + + projects = this.repository.findByNameOrForkCount(NAME_0, FORK_COUNT_1); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_4)); + } + + @Test + public void testFindByWithAndPartition() { + List projects = this.repository.findByNameAndCreator(NAME_1, CREATOR_1); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_1)); + + projects = this.repository.findByNameAndCreator(NAME_0, CREATOR_1); + + Assert.assertTrue(projects.isEmpty()); + + projects = this.repository.findByNameAndCreator(NAME_0, CREATOR_0); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + } + + @Test + public void testFindByWithOrPartition() { + List projects = this.repository.findByNameOrCreator(NAME_2, CREATOR_2); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_2)); + + projects = this.repository.findByNameOrCreator(FAKE_NAME, FAKE_CREATOR); + + Assert.assertTrue(projects.isEmpty()); + + projects = this.repository.findByNameOrCreator(NAME_0, CREATOR_1); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_4)); + } + + @Test + public void testFindByWithAndOr() { + List projects = repository.findByNameAndCreatorOrForkCount(NAME_0, CREATOR_1, FORK_COUNT_2); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_2)); + + projects = repository.findByNameAndCreatorOrForkCount(NAME_1, CREATOR_2, FAKE_COUNT); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByNameAndCreatorOrForkCount(NAME_1, CREATOR_1, FORK_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2)); + } + + @Test + public void testFindByWithOrAnd() { + List projects = repository.findByNameOrCreatorAndForkCount(NAME_0, CREATOR_1, FORK_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + + projects = repository.findByNameOrCreatorAndForkCount(FAKE_NAME, CREATOR_1, FORK_COUNT_2); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByNameOrCreatorAndForkCount(NAME_1, CREATOR_2, FORK_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2)); + } + + @Test + public void testFindByWithOrOr() { + List projects = repository.findByNameOrCreatorOrForkCount(NAME_0, CREATOR_1, FORK_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_4)); + + projects = repository.findByNameOrCreatorOrForkCount(FAKE_NAME, FAKE_CREATOR, FAKE_COUNT); + + Assert.assertTrue(projects.isEmpty()); + } + + @Test + public void testFindByWithOrAndOr() { + List projects = repository.findByNameOrCreatorAndForkCountOrStarCount(NAME_1, CREATOR_0, + FORK_COUNT_2, STAR_COUNT_3); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_3)); + + projects = repository.findByNameOrCreatorAndForkCountOrStarCount(NAME_1, CREATOR_0, FORK_COUNT_0, STAR_COUNT_3); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_3, PROJECT_4)); + + projects = repository.findByNameOrCreatorAndForkCountOrStarCount(FAKE_NAME, CREATOR_1, + FORK_COUNT_0, FAKE_COUNT); + + Assert.assertTrue(projects.isEmpty()); + } + + @Test + public void testFindByGreaterThan() { + List projects = repository.findByForkCountGreaterThan(FORK_COUNT_1); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_2, PROJECT_3)); + + projects = repository.findByForkCountGreaterThan(FAKE_COUNT); + + Assert.assertTrue(projects.isEmpty()); + } + + @Test + public void testFindByGreaterThanWithAndOr() { + List projects = repository.findByCreatorAndForkCountGreaterThan(CREATOR_2, FORK_COUNT_1); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_2)); + + projects = repository.findByCreatorAndForkCountGreaterThan(CREATOR_0, FORK_COUNT_1); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByCreatorOrForkCountGreaterThan(CREATOR_0, FORK_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_3, PROJECT_4)); + } + + @Test + public void testFindByLessThan() { + List projects = repository.findByStarCountLessThan(STAR_COUNT_0); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByStarCountLessThan(STAR_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_4)); + } + + @Test + public void testFindByLessThanEqual() { + List projects = repository.findByForkCountLessThanEqual(STAR_COUNT_MIN); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByForkCountLessThanEqual(STAR_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_4)); + } + + @Test + public void testFindByLessThanAndGreaterThan() { + List projects = repository.findByStarCountLessThanAndForkCountGreaterThan(STAR_COUNT_0, FORK_COUNT_3); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByStarCountLessThanAndForkCountGreaterThan(STAR_COUNT_3, FORK_COUNT_0); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2)); + } + + @Test + public void testFindByLessThanEqualsAndGreaterThanEquals() { + List projects = repository.findByForkCountLessThanEqualAndStarCountGreaterThan( + STAR_COUNT_MIN, FORK_COUNT_0); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByForkCountLessThanEqualAndStarCountGreaterThan(STAR_COUNT_3, FORK_COUNT_0); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2, PROJECT_3)); + } + + @Test + public void testFindByGreaterThanEqual() { + List projects = repository.findByStarCountGreaterThanEqual(STAR_COUNT_MAX); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByStarCountGreaterThanEqual(STAR_COUNT_2); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_2, PROJECT_3)); + } + + @Test + public void testFindByGreaterThanEqualAnd() { + List projects = repository.findByForkCountGreaterThanEqualAndCreator(FORK_COUNT_MAX, CREATOR_2); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByForkCountGreaterThanEqualAndCreator(FORK_COUNT_0, CREATOR_0); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + } + + @Test + public void testFindByTrue() { + final List projects = repository.findByHasReleasedTrue(); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_3)); + } + + @Test + public void testFindByFalse() { + final List projects = repository.findByHasReleasedFalse(); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_4)); + } + + @Test + public void testFindByTrueFalseWithAnd() { + List projects = repository.findByHasReleasedTrueAndCreator(CREATOR_3); + assertProjectListEquals(projects, Arrays.asList(PROJECT_3)); + + projects = repository.findByHasReleasedFalseAndCreator(CREATOR_3); + assertProjectListEquals(projects, Arrays.asList()); + } + + @Test + public void testFindByTrueFalseWithOr() { + List projects = repository.findByHasReleasedTrueOrCreator(CREATOR_0); + assertProjectListEquals(projects, PROJECTS); + + projects = repository.findByHasReleasedFalseOrCreator(CREATOR_3); + assertProjectListEquals(projects, Arrays.asList(PROJECT_3, PROJECT_4)); + } + + @Test + public void findByIdWithPartitionKey() { + final Optional project = repository.findById(PROJECT_0.getId(), + new PartitionKey(entityInformation.getPartitionKeyFieldValue(PROJECT_0))); + + Assert.assertTrue(project.isPresent()); + + Assert.assertEquals(project.get(), PROJECT_0); + } + + @Test + public void findByIdWithPartitionKeyNotFound() { + final Optional project = repository.findById("unknown-id", + new PartitionKey("unknown-partition-key")); + + Assert.assertFalse(project.isPresent()); + } + + + @Test + public void testFindByIn() { + List projects = repository.findByCreatorIn(Collections.singleton(FAKE_CREATOR)); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByCreatorIn(Arrays.asList(CREATOR_1, CREATOR_2)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2)); + + projects = repository.findByCreatorIn(Arrays.asList(CREATOR_0, FAKE_CREATOR)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + } + + @Test + public void testFindByInWithAnd() { + List projects = repository.findByCreatorInAndStarCountIn(Arrays.asList(CREATOR_0, CREATOR_1), + Arrays.asList(STAR_COUNT_2, STAR_COUNT_3)); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByCreatorInAndStarCountIn(Arrays.asList(CREATOR_0, CREATOR_1), + Arrays.asList(STAR_COUNT_0, STAR_COUNT_2)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + + projects = repository.findByCreatorInAndStarCountIn(Arrays.asList(CREATOR_0, CREATOR_1, CREATOR_2), + Arrays.asList(STAR_COUNT_0, STAR_COUNT_1, STAR_COUNT_2)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_4)); + } + + @Test + public void testFindByNotIn() { + List projects = repository.findByCreatorNotIn( + Arrays.asList(CREATOR_0, CREATOR_1, CREATOR_2, CREATOR_3)); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByCreatorNotIn(Arrays.asList(CREATOR_1, CREATOR_2)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_3, PROJECT_4)); + + projects = repository.findByCreatorNotIn(Arrays.asList(CREATOR_0, FAKE_CREATOR)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_1, PROJECT_2, PROJECT_3)); + } + + @Test + public void testFindByInWithNotIn() { + List projects = repository.findByCreatorInAndStarCountNotIn(Collections.singletonList(FAKE_CREATOR), + Arrays.asList(STAR_COUNT_2, STAR_COUNT_3)); + + Assert.assertTrue(projects.isEmpty()); + + projects = repository.findByCreatorInAndStarCountNotIn(Arrays.asList(CREATOR_0, CREATOR_1), + Arrays.asList(STAR_COUNT_0, STAR_COUNT_2)); + + assertProjectListEquals(projects, Collections.singletonList(PROJECT_1)); + + projects = repository.findByCreatorInAndStarCountNotIn(Arrays.asList(CREATOR_0, CREATOR_1, CREATOR_2), + Arrays.asList(STAR_COUNT_1, STAR_COUNT_2)); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_4)); + } + + @Test + public void testFindByNameIsNull() { + List projects = repository.findByNameIsNull(); + + Assert.assertTrue(projects.isEmpty()); + + final Project nullNameProject = new Project("id-999", null, CREATOR_0, true, STAR_COUNT_0, + FORK_COUNT_0); + + this.repository.save(nullNameProject); + projects = repository.findByNameIsNull(); + + assertProjectListEquals(projects, Collections.singletonList(nullNameProject)); + } + + @Test + public void testFindByNameIsNotNull() { + List projects = repository.findByNameIsNotNull(); + + assertProjectListEquals(projects, PROJECTS); + + this.repository.deleteAll(); + this.repository.save(new Project("id-999", null, CREATOR_0, true, STAR_COUNT_0, FORK_COUNT_0)); + + projects = repository.findByNameIsNotNull(); + + Assert.assertTrue(projects.isEmpty()); + } + + @Test + public void testFindByNameIsNullWithAnd() { + List projects = repository.findByNameIsNullAndForkCount(FORK_COUNT_MAX); + + Assert.assertTrue(projects.isEmpty()); + + final Project nullNameProject = new Project("id-999", null, CREATOR_0, true, STAR_COUNT_0, + FORK_COUNT_0); + + this.repository.save(nullNameProject); + projects = repository.findByNameIsNullAndForkCount(FORK_COUNT_0); + + assertProjectListEquals(projects, Collections.singletonList(nullNameProject)); + } + + @Test + public void testFindByNameIsNotNullWithAnd() { + List projects = repository.findByNameIsNotNullAndHasReleased(true); + + assertProjectListEquals(projects, Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_3)); + + this.repository.deleteAll(); + this.repository.save(new Project("id-999", null, CREATOR_0, true, STAR_COUNT_0, FORK_COUNT_0)); + + projects = repository.findByNameIsNotNullAndHasReleased(true); + Assert.assertTrue(projects.isEmpty()); + } + + @Test + public void testFindAllByPartitionKey() { + List findAll = + repository.findAll(new PartitionKey(CREATOR_0)); + // Since there are two projects with creator_0 + assertThat(findAll.size()).isEqualTo(2); + assertThat(findAll.containsAll(Lists.newArrayList(PROJECT_0, PROJECT_4))).isTrue(); + + findAll = repository.findAll(new PartitionKey(CREATOR_1)); + // Since there is one projects with creator_1 + assertThat(findAll.size()).isEqualTo(1); + assertThat(findAll.contains(PROJECT_1)).isTrue(); + + + findAll = repository.findAll(new PartitionKey(CREATOR_2)); + // Since there is one projects with creator_2 + assertThat(findAll.size()).isEqualTo(1); + assertThat(findAll.contains(PROJECT_2)).isTrue(); + + findAll = repository.findAll(new PartitionKey(CREATOR_3)); + // Since there is one projects with creator_3 + assertThat(findAll.size()).isEqualTo(1); + assertThat(findAll.contains(PROJECT_3)).isTrue(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java new file mode 100644 index 000000000000..dd952e74dc53 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java @@ -0,0 +1,251 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; +import com.microsoft.azure.spring.data.cosmosdb.domain.SortedProject; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.SortedProjectRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static com.microsoft.azure.spring.data.cosmosdb.common.PageTestUtils.validateLastPage; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ProjectRepositorySortIT { + + private static final String ID_0 = "id-0"; + private static final String ID_1 = "id-1"; + private static final String ID_2 = "id-2"; + private static final String ID_3 = "id-3"; + private static final String ID_4 = "id-4"; + + private static final String NAME_0 = "name-0"; + private static final String NAME_1 = "name-1"; + private static final String NAME_2 = "name-2"; + private static final String NAME_3 = "NAME-3"; + private static final String NAME_4 = "name-4"; + + private static final String CREATOR_0 = "creator-0"; + private static final String CREATOR_1 = "creator-1"; + private static final String CREATOR_2 = "creator-2"; + private static final String CREATOR_3 = "creator-3"; + private static final String CREATOR_4 = "creator-4"; + + private static final Long STAR_COUNT_0 = 0L; + private static final Long STAR_COUNT_1 = 1L; + private static final Long STAR_COUNT_2 = 2L; + private static final Long STAR_COUNT_3 = 3L; + private static final Long STAR_COUNT_4 = 4L; + + private static final Long FORK_COUNT_0 = 0L; + private static final Long FORK_COUNT_1 = 1L; + private static final Long FORK_COUNT_2 = 2L; + private static final Long FORK_COUNT_3 = 3L; + private static final Long FORK_COUNT_4 = FORK_COUNT_3; + + private static final SortedProject PROJECT_0 = new SortedProject(ID_0, NAME_0, CREATOR_0, + true, STAR_COUNT_0, FORK_COUNT_0); + private static final SortedProject PROJECT_1 = new SortedProject(ID_1, NAME_1, CREATOR_1, + true, STAR_COUNT_1, FORK_COUNT_1); + private static final SortedProject PROJECT_2 = new SortedProject(ID_2, NAME_2, CREATOR_2, + true, STAR_COUNT_2, FORK_COUNT_2); + private static final SortedProject PROJECT_3 = new SortedProject(ID_3, NAME_3, CREATOR_3, + true, STAR_COUNT_3, FORK_COUNT_3); + private static final SortedProject PROJECT_4 = new SortedProject(ID_4, NAME_4, CREATOR_4, + true, STAR_COUNT_4, FORK_COUNT_4); + + private static final List PROJECTS = Arrays.asList(PROJECT_4, PROJECT_3, + PROJECT_2, PROJECT_1, PROJECT_0); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(SortedProject.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private SortedProjectRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.saveAll(PROJECTS); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAllSortASC() { + final Sort sort = Sort.by(Sort.Direction.ASC, "starCount"); + final List projects = Lists.newArrayList(this.repository.findAll(sort)); + + PROJECTS.sort(Comparator.comparing(SortedProject::getStarCount)); + + Assert.assertEquals(PROJECTS.size(), projects.size()); + Assert.assertEquals(PROJECTS, projects); + } + + @Test + public void testFindAllSortDESC() { + final Sort sort = Sort.by(Sort.Direction.DESC, "creator"); + final List projects = Lists.newArrayList(this.repository.findAll(sort)); + + PROJECTS.sort(Comparator.comparing(SortedProject::getCreator).reversed()); + + Assert.assertEquals(PROJECTS.size(), projects.size()); + Assert.assertEquals(PROJECTS, projects); + } + + @Test + public void testFindAllUnSorted() { + final Sort sort = Sort.unsorted(); + final List projects = Lists.newArrayList(this.repository.findAll(sort)); + + PROJECTS.sort(Comparator.comparing(SortedProject::getId)); + projects.sort(Comparator.comparing(SortedProject::getId)); + + Assert.assertEquals(PROJECTS.size(), projects.size()); + Assert.assertEquals(PROJECTS, projects); + } + + @Test(expected = CosmosDBAccessException.class) + public void testFindAllSortMoreThanOneOrderException() { + final Sort sort = Sort.by(Sort.Direction.ASC, "name", "creator"); + + this.repository.findAll(sort); + } + + @Test(expected = IllegalArgumentException.class) + public void testFindAllSortIgnoreCaseException() { + final Sort.Order order = Sort.Order.by("name").ignoreCase(); + final Sort sort = Sort.by(order); + + this.repository.findAll(sort); + } + + @Test(expected = CosmosDBAccessException.class) + public void testFindAllSortMissMatchException() { + final Sort sort = Sort.by(Sort.Direction.ASC, "fake-name"); + + this.repository.findAll(sort); + } + + public void testFindAllSortWithIdName() { + final List projectListSortedById = Lists.newArrayList(PROJECTS); + projectListSortedById.sort(Comparator.comparing(SortedProject::getId)); + + final Sort sort = Sort.by(Sort.Direction.ASC, "id"); + final List results = StreamSupport.stream(this.repository.findAll(sort).spliterator(), + false) + .collect(Collectors.toList()); + + Assert.assertEquals(projectListSortedById, results); + } + + @Test + public void testFindSortWithOr() { + final Sort sort = Sort.by(Sort.Direction.ASC, "starCount"); + final List projects = Lists.newArrayList(this.repository.findByNameOrCreator(NAME_0, CREATOR_3, + sort)); + final List references = Arrays.asList(PROJECT_0, PROJECT_3); + + references.sort(Comparator.comparing(SortedProject::getStarCount)); + + Assert.assertEquals(references.size(), projects.size()); + Assert.assertEquals(references, projects); + } + + @Test + public void testFindSortWithAnd() { + final Sort sort = Sort.by(Sort.Direction.ASC, "forkCount"); + final List projects = Lists.newArrayList(repository.findByNameAndCreator(NAME_0, CREATOR_0, + sort)); + final List references = Arrays.asList(PROJECT_0); + + references.sort(Comparator.comparing(SortedProject::getStarCount)); + + Assert.assertEquals(references.size(), projects.size()); + Assert.assertEquals(references, projects); + } + + @Test + public void testFindSortWithEqual() { + final Sort sort = Sort.by(Sort.Direction.DESC, "name"); + final List projects = Lists.newArrayList(this.repository.findByForkCount(FORK_COUNT_3, sort)); + final List references = Arrays.asList(PROJECT_3, PROJECT_4); + + references.sort(Comparator.comparing(SortedProject::getName).reversed()); + + Assert.assertEquals(references.size(), projects.size()); + Assert.assertEquals(references, projects); + } + + @Test + public void testFindAllWithPageableAndSort() { + final Sort sort = Sort.by(Sort.Direction.DESC, "name"); + final Pageable pageable = new CosmosPageRequest(0, 5, null, sort); + + final Page result = this.repository.findAll(pageable); + + final List references = Arrays.asList(PROJECT_0, PROJECT_1, PROJECT_2, PROJECT_3, PROJECT_4); + references.sort(Comparator.comparing(SortedProject::getName).reversed()); + + Assert.assertEquals(references.size(), result.getContent().size()); + Assert.assertEquals(references, result.getContent()); + validateLastPage(result, 5); + } + + @Test + public void testFindWithPageableAndSort() { + final Sort sort = Sort.by(Sort.Direction.DESC, "name"); + final Pageable pageable = new CosmosPageRequest(0, 5, null, sort); + + final Page result = this.repository.findByForkCount(FORK_COUNT_3, pageable); + + final List references = Arrays.asList(PROJECT_3, PROJECT_4); + + references.sort(Comparator.comparing(SortedProject::getName).reversed()); + + Assert.assertEquals(references.size(), result.getContent().size()); + Assert.assertEquals(references, result.getContent()); + validateLastPage(result, result.getContent().size()); + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java new file mode 100644 index 000000000000..deba6ec4e626 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Question; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.ProjectRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.QuestionRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class QuestionRepositoryIT { + + private static final String QUESTION_ID = "question-id"; + + private static final String QUESTION_URL = "http://xxx.html"; + + private static final Question QUESTION = new Question(QUESTION_ID, QUESTION_URL); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Question.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private QuestionRepository repository; + + @Autowired + private ProjectRepository projectRepository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.save(QUESTION); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindById() { + final Optional optional = this.repository.findById(QUESTION_ID); + + Assert.assertTrue(optional.isPresent()); + Assert.assertEquals(QUESTION, optional.get()); + } + + @Test + public void testFindByIdNull() { + final Optional byId = this.repository.findById(QUESTION_URL); + Assert.assertFalse(byId.isPresent()); + } + + @Test + public void testFindAll() { + final List questions = Lists.newArrayList(this.repository.findAll()); + + Assert.assertEquals(Collections.singletonList(QUESTION), questions); + } + + @Test + public void testDelete() { + Optional optional = this.repository.findById(QUESTION_ID); + + Assert.assertTrue(optional.isPresent()); + Assert.assertEquals(QUESTION, optional.get()); + + this.repository.delete(QUESTION); + optional = this.repository.findById(QUESTION_ID); + + Assert.assertFalse(optional.isPresent()); + } +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java new file mode 100644 index 000000000000..140cff164df8 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java @@ -0,0 +1,260 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.azure.data.cosmos.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Course; +import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.ReactiveCourseRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class ReactiveCourseRepositoryIT { + + private static final String COURSE_ID_1 = "1"; + private static final String COURSE_ID_2 = "2"; + private static final String COURSE_ID_3 = "3"; + private static final String COURSE_ID_4 = "4"; + private static final String COURSE_ID_5 = "5"; + + private static final String COURSE_NAME_1 = "Course1"; + private static final String COURSE_NAME_2 = "Course2"; + private static final String COURSE_NAME_3 = "Course3"; + private static final String COURSE_NAME_4 = "Course4"; + private static final String COURSE_NAME_5 = "Course5"; + + private static final String DEPARTMENT_NAME_1 = "Department1"; + private static final String DEPARTMENT_NAME_2 = "Department2"; + private static final String DEPARTMENT_NAME_3 = "Department3"; + + private static final Course COURSE_1 = new Course(COURSE_ID_1, COURSE_NAME_1, DEPARTMENT_NAME_3); + private static final Course COURSE_2 = new Course(COURSE_ID_2, COURSE_NAME_2, DEPARTMENT_NAME_2); + private static final Course COURSE_3 = new Course(COURSE_ID_3, COURSE_NAME_3, DEPARTMENT_NAME_2); + private static final Course COURSE_4 = new Course(COURSE_ID_4, COURSE_NAME_4, DEPARTMENT_NAME_1); + private static final Course COURSE_5 = new Course(COURSE_ID_5, COURSE_NAME_5, DEPARTMENT_NAME_1); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Course.class); + + private static ReactiveCosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private ReactiveCosmosTemplate template; + + @Autowired + private ReactiveCourseRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + final Flux savedFlux = repository.saveAll(Arrays.asList(COURSE_1, COURSE_2, + COURSE_3, COURSE_4)); + StepVerifier.create(savedFlux).thenConsumeWhile(course -> true).expectComplete().verify(); + isSetupDone = true; + } + + @After + public void cleanup() { + final Mono deletedMono = repository.deleteAll(); + StepVerifier.create(deletedMono).thenAwait().verifyComplete(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindById() { + final Mono idMono = repository.findById(COURSE_ID_4); + StepVerifier.create(idMono).expectNext(COURSE_4).expectComplete().verify(); + } + + @Test + public void testFindByIdAndPartitionKey() { + final Mono idMono = repository.findById(COURSE_ID_4, + new PartitionKey(entityInformation.getPartitionKeyFieldValue(COURSE_4))); + StepVerifier.create(idMono).expectNext(COURSE_4).expectComplete().verify(); + } + + @Test + public void testFindByIdAsPublisher() { + final Mono byId = repository.findById(Mono.just(COURSE_ID_1)); + StepVerifier.create(byId).expectNext(COURSE_1).verifyComplete(); + } + + @Test + public void testFindAllWithSort() { + final Flux sortAll = repository.findAll(Sort.by(Sort.Order.desc("name"))); + StepVerifier.create(sortAll).expectNext(COURSE_4, COURSE_3, COURSE_2, COURSE_1).verifyComplete(); + } + + @Test + public void testFindByIdNotFound() { + final Mono idMono = repository.findById("10"); + // Expect an empty mono as return value + StepVerifier.create(idMono).expectComplete().verify(); + } + + @Test + public void testFindByIdAndPartitionKeyNotFound() { + final Mono idMono = repository.findById("10", + new PartitionKey(entityInformation.getPartitionKeyFieldValue(COURSE_1))); + // Expect an empty mono as return value + StepVerifier.create(idMono).expectComplete().verify(); + } + + @Test + public void testFindAll() { + final Flux allFlux = repository.findAll(); + StepVerifier.create(allFlux).expectNextCount(4).verifyComplete(); + } + + @Test + public void testInsert() { + final Mono save = repository.save(COURSE_5); + StepVerifier.create(save).expectNext(COURSE_5).verifyComplete(); + } + + @Test + public void testUpsert() { + Mono save = repository.save(COURSE_1); + StepVerifier.create(save).expectNext(COURSE_1).expectComplete().verify(); + + save = repository.save(COURSE_1); + StepVerifier.create(save).expectNext(COURSE_1).expectComplete().verify(); + } + + @Test + public void testDeleteByIdWithoutPartitionKey() { + final Mono deleteMono = repository.deleteById(COURSE_1.getCourseId()); + StepVerifier.create(deleteMono).expectError(CosmosDBAccessException.class).verify(); + } + + @Test + public void testDeleteByIdAndPartitionKey() { + final Mono deleteMono = repository.deleteById(COURSE_1.getCourseId(), + new PartitionKey(entityInformation.getPartitionKeyFieldValue(COURSE_1))); + StepVerifier.create(deleteMono).verifyComplete(); + + final Mono byId = repository.findById(COURSE_ID_1, + new PartitionKey(entityInformation.getPartitionKeyFieldValue(COURSE_1))); + // Expect an empty mono as return value + StepVerifier.create(byId).verifyComplete(); + } + + @Test + public void testDeleteByEntity() { + final Mono deleteMono = repository.delete(COURSE_4); + StepVerifier.create(deleteMono).verifyComplete(); + + final Mono byId = repository.findById(COURSE_ID_4); + // Expect an empty mono as return value + StepVerifier.create(byId).expectComplete().verify(); + } + + @Test + public void testDeleteByIdNotFound() { + final Mono deleteMono = repository.deleteById(COURSE_ID_5); + StepVerifier.create(deleteMono).expectError(CosmosDBAccessException.class).verify(); + } + + @Test + public void testDeleteByEntityNotFound() { + final Mono deleteMono = repository.delete(COURSE_5); + StepVerifier.create(deleteMono).expectError(CosmosDBAccessException.class).verify(); + } + + @Test + public void testCountAll() { + final Mono countMono = repository.count(); + StepVerifier.create(countMono).expectNext(4L).verifyComplete(); + } + + @Test + public void testFindByDepartmentIn() { + final Flux byDepartmentIn = + repository.findByDepartmentIn(Collections.singletonList(DEPARTMENT_NAME_2)); + StepVerifier.create(byDepartmentIn).expectNextCount(2).verifyComplete(); + } + + @Test + public void testFindAllByPartitionKey() { + final Mono save = repository.save(COURSE_5); + StepVerifier.create(save).expectNext(COURSE_5).verifyComplete(); + + Flux findAll = repository.findAll(new PartitionKey(DEPARTMENT_NAME_1)); + // Since there are two courses with department_1 + final AtomicBoolean courseFound = new AtomicBoolean(false); + StepVerifier.create(findAll).expectNextCount(2).verifyComplete(); + StepVerifier.create(findAll) + .expectNextMatches(course -> { + if (course.equals(COURSE_4)) { + courseFound.set(true); + } else if (course.equals(COURSE_5)) { + courseFound.set(false); + } else { + return false; + } + return true; + }) + .expectNextMatches(course -> { + if (courseFound.get()) { + return course.equals(COURSE_5); + } else { + return course.equals(COURSE_4); + } + }) + .verifyComplete(); + + findAll = repository.findAll(new PartitionKey(DEPARTMENT_NAME_3)); + // Since there are two courses with department_3 + StepVerifier.create(findAll).expectNext(COURSE_1).verifyComplete(); + + findAll = repository.findAll(new PartitionKey(DEPARTMENT_NAME_2)); + // Since there are two courses with department_2 + StepVerifier.create(findAll).expectNextCount(2).verifyComplete(); + StepVerifier.create(findAll) + .expectNextMatches(course -> { + if (course.equals(COURSE_2)) { + courseFound.set(true); + } else if (course.equals(COURSE_3)) { + courseFound.set(false); + } else { + return false; + } + return true; + }) + .expectNextMatches(course -> { + if (courseFound.get()) { + return course.equals(COURSE_3); + } else { + return course.equals(COURSE_2); + } + }) + .verifyComplete(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java new file mode 100644 index 000000000000..16012a8e3a1d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; +import com.microsoft.azure.spring.data.cosmosdb.core.convert.ObjectMapperFactory; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; +import com.microsoft.azure.spring.data.cosmosdb.domain.SpELBeanStudent; +import com.microsoft.azure.spring.data.cosmosdb.domain.SpELPropertyStudent; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.domain.EntityScanner; +import org.springframework.context.ApplicationContext; +import org.springframework.data.annotation.Persistent; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class SpELCosmosDBAnnotationIT { + private static final SpELPropertyStudent TEST_PROPERTY_STUDENT = + new SpELPropertyStudent(TestConstants.ID_1, TestConstants.FIRST_NAME, + TestConstants.LAST_NAME); + + @Value("${cosmosdb.uri}") + private String dbUri; + + @Value("${cosmosdb.key}") + private String dbKey; + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private CosmosTemplate cosmosTemplate; + + private static CosmosTemplate staticTemplate; + private static CosmosEntityInformation cosmosEntityInformation; + + @Before + public void setUp() { + if (staticTemplate == null) { + staticTemplate = cosmosTemplate; + } + } + + @AfterClass + public static void afterClassCleanup() { + if (cosmosEntityInformation != null) { + staticTemplate.deleteContainer(cosmosEntityInformation.getContainerName()); + } + } + + @Test + public void testDynamicContainerNameWithPropertySourceExpression() { + final CosmosEntityInformation propertyStudentInfo = + new CosmosEntityInformation<>(SpELPropertyStudent.class); + + assertEquals(TestConstants.DYNAMIC_PROPERTY_COLLECTION_NAME, propertyStudentInfo.getContainerName()); + } + + @Test + public void testDynamicContainerNameWithBeanExpression() { + final CosmosEntityInformation beanStudentInfo = + new CosmosEntityInformation<>(SpELBeanStudent.class); + + assertEquals(TestConstants.DYNAMIC_BEAN_COLLECTION_NAME, beanStudentInfo.getContainerName()); + } + + @Test + public void testDatabaseOperationsOnDynamicallyNamedCollection() throws ClassNotFoundException { + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(dbUri, dbKey, TestConstants.DB_NAME).build(); + final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); + + cosmosEntityInformation = new CosmosEntityInformation<>(SpELPropertyStudent.class); + final CosmosMappingContext dbContext = new CosmosMappingContext(); + dbContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + + final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + final MappingCosmosConverter mappingConverter = new MappingCosmosConverter(dbContext, objectMapper); + staticTemplate = new CosmosTemplate(dbFactory, mappingConverter, TestConstants.DB_NAME); + + staticTemplate.createContainerIfNotExists(cosmosEntityInformation); + + final SpELPropertyStudent insertedRecord = + staticTemplate.insert(cosmosEntityInformation.getContainerName(), TEST_PROPERTY_STUDENT, null); + assertNotNull(insertedRecord); + + final SpELPropertyStudent readRecord = + staticTemplate.findById(TestConstants.DYNAMIC_PROPERTY_COLLECTION_NAME, + insertedRecord.getId(), SpELPropertyStudent.class); + assertNotNull(readRecord); + } + +} + diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java new file mode 100644 index 000000000000..b186197af719 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils; +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.inheritance.Square; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.SquareRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class SquareRepositoryIT { + private Square square1 = new Square("id_1", 1, 1); + private Square square2 = new Square("id_2", 2, 4); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Square.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private SquareRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + repository.save(square1); + repository.save(square2); + isSetupDone = true; + } + + @After + public void cleanup() { + repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindAll() { + final List result = TestUtils.toList(repository.findAll()); + + assertThat(result.size()).isEqualTo(2); + } + + @Test + public void testFindIncludeInheritedFields() { + final Optional result = repository.findById(square1.getId()); + + assertThat(result.get()).isNotNull(); + assertThat(result.get().getId().equals(square1.getId())); + assertThat(result.get().getLength()).isEqualTo(square1.getLength()); + assertThat(result.get().getArea()).isEqualTo(square1.getArea()); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java new file mode 100644 index 000000000000..9b0058e7f905 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.integration; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Student; +import com.microsoft.azure.spring.data.cosmosdb.repository.TestRepositoryConfig; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.StudentRepository; +import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = TestRepositoryConfig.class) +public class StudentRepositoryIT { + public static final String ID_0 = "id-0"; + public static final String ID_1 = "id-1"; + public static final String ID_2 = "id-2"; + public static final String ID_3 = "id-3"; + + public static final String FIRST_NAME_0 = "Mary"; + public static final String FIRST_NAME_1 = "Cheng"; + public static final String FIRST_NAME_2 = "Zheng"; + public static final String FIRST_NAME_3 = "Zhen"; + + public static final String LAST_NAME_0 = "Chen"; + public static final String LAST_NAME_1 = "Ch"; + public static final String LAST_NAME_2 = "N"; + public static final String LAST_NAME_3 = "H"; + + public static final String SUB_FIRST_NAME = "eng"; + + private static final Student STUDENT_0 = new Student(ID_0, FIRST_NAME_0, LAST_NAME_0); + private static final Student STUDENT_1 = new Student(ID_1, FIRST_NAME_1, LAST_NAME_1); + private static final Student STUDENT_2 = new Student(ID_2, FIRST_NAME_2, LAST_NAME_2); + private static final Student STUDENT_3 = new Student(ID_3, FIRST_NAME_3, LAST_NAME_3); + private static final List PEOPLE = Arrays.asList(STUDENT_0, STUDENT_1, STUDENT_2, STUDENT_3); + + private static final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Student.class); + + private static CosmosTemplate staticTemplate; + private static boolean isSetupDone; + + @Autowired + private CosmosTemplate template; + + @Autowired + private StudentRepository repository; + + @Before + public void setUp() { + if (!isSetupDone) { + staticTemplate = template; + template.createContainerIfNotExists(entityInformation); + } + this.repository.saveAll(PEOPLE); + isSetupDone = true; + } + + @After + public void cleanup() { + this.repository.deleteAll(); + } + + @AfterClass + public static void afterClassCleanup() { + staticTemplate.deleteContainer(entityInformation.getContainerName()); + } + + @Test + public void testFindByContaining() { + final List people = repository.findByFirstNameContaining(SUB_FIRST_NAME); + final List reference = Arrays.asList(STUDENT_1, STUDENT_2); + + assertPeopleEquals(people, reference); + } + + @Test + public void testFindByContainingWithAnd() { + final List people = repository.findByFirstNameContainingAndLastNameContaining("eng", "h"); + final List reference = Arrays.asList(STUDENT_1); + + assertPeopleEquals(people, reference); + } + + @Test + public void testFindByEndsWith() { + final List people = repository.findByFirstNameEndsWith("en"); + final List reference = Arrays.asList(STUDENT_3); + + assertPeopleEquals(people, reference); + } + + @Test + public void testFindByNot() { + final List people = repository.findByFirstNameNot("Mary"); + final List reference = Arrays.asList(STUDENT_1, STUDENT_2, STUDENT_3); + + assertPeopleEquals(people, reference); + } + + @Test + public void testFindByStartsWith() { + List people = repository.findByFirstNameStartsWith("Z"); + + assertPeopleEquals(people, Arrays.asList(STUDENT_2, STUDENT_3)); + + people = repository.findByLastNameStartsWith("C"); + + assertPeopleEquals(people, Arrays.asList(STUDENT_0, STUDENT_1)); + } + + @Test + public void testFindByStartsWithAndEndsWith() { + List people = repository.findByFirstNameStartsWithAndLastNameEndingWith("Z", "H"); + + assertPeopleEquals(people, Arrays.asList(STUDENT_3)); + + people = repository.findByFirstNameStartsWithAndLastNameEndingWith("Z", "en"); + + assertPeopleEquals(people, Arrays.asList()); + } + + @Test + public void testFindByStartsWithOrContaining() { + List people = repository.findByFirstNameStartsWithOrLastNameContaining("Zhen", "C"); + + assertPeopleEquals(people, PEOPLE); + + people = repository.findByFirstNameStartsWithOrLastNameContaining("M", "N"); + + assertPeopleEquals(people, Arrays.asList(STUDENT_0, STUDENT_2)); + } + + @Test + public void testFindByContainingAndNot() { + final List people = repository.findByFirstNameContainingAndLastNameNot("Zhe", "N"); + + assertPeopleEquals(people, Arrays.asList(STUDENT_3)); + } + + private void assertPeopleEquals(List people, List reference) { + people.sort(Comparator.comparing(Student::getId)); + reference.sort(Comparator.comparing(Student::getId)); + + Assert.assertEquals(reference, people); + } + + @Test + public void testExists() { + assertTrue(repository.existsByFirstName(FIRST_NAME_0)); + assertFalse(repository.existsByFirstName("xxx")); + + assertTrue(repository.existsByLastNameContaining("N")); + assertFalse(repository.existsByLastNameContaining("X")); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java new file mode 100644 index 000000000000..1f7a6055df0e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface AddressRepository extends CosmosRepository { + void deleteByPostalCodeAndCity(String postalCode, String city); + + void deleteByCity(String city); + + List
findByPostalCodeAndCity(String postalCode, String city); + + List
findByCity(String city); + + List
findByPostalCode(String postalCode); + + List
findByStreetOrCity(String street, String city); + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java new file mode 100644 index 000000000000..3d52e998547b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Contact; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ContactRepository extends CosmosRepository { + List findByTitle(String title); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java new file mode 100644 index 000000000000..9c1a0e5d33e4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Customer; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; + +import java.util.List; + +public interface CustomerRepository extends CosmosRepository { + List findByUser_Name(String name); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java new file mode 100644 index 000000000000..5c7cb1b9a575 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.IntegerIdDomain; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface IntegerIdDomainRepository extends CosmosRepository { + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java new file mode 100644 index 000000000000..f6544d0462c4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Memo; +import com.microsoft.azure.spring.data.cosmosdb.domain.Importance; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; + +@Repository +public interface MemoRepository extends CosmosRepository { + List findMemoByDate(Date date); + + List findMemoByImportance(Importance importance); + + List findByDateBefore(Date date); + + List findByDateBeforeAndMessage(Date date, String message); + + List findByDateBeforeOrMessage(Date date, String message); + + List findByDateAfter(Date date); + + List findByDateAfterAndMessage(Date date, String message); + + List findByDateAfterOrMessage(Date date, String message); + + List findByDateBetween(Date startDate, Date endDate); + + List findByDateBetweenAndMessage(Date startDate, Date endDate, String message); + + List findByDateBetweenOrMessage(Date startDate, Date endDate, String message); + + List findByMessageStartsWith(String message); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java new file mode 100644 index 000000000000..a2e864969afc --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.PageableAddress; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PageableAddressRepository extends PagingAndSortingRepository{ + Page findByStreet(String street, Pageable pageable); + + Page findByCity(String city, Pageable pageable); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java new file mode 100644 index 000000000000..7630c84672d2 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.PageableMemo; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PageableMemoRepository extends PagingAndSortingRepository { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java new file mode 100644 index 000000000000..afc831158210 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.PageablePerson; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PageablePersonRepository extends PagingAndSortingRepository { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java new file mode 100644 index 000000000000..f88f6eb54b79 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PartitionPersonRepository extends CosmosRepository { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java new file mode 100644 index 000000000000..95cbe3ecc681 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PersonRepository extends CosmosRepository { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java new file mode 100644 index 000000000000..a8b0049754df --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Project; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.Collection; +import java.util.List; + +public interface ProjectRepository extends CosmosRepository { + + List findByNameAndStarCount(String name, Long startCount); + + List findByNameOrForkCount(String name, Long forkCount); + + List findByNameAndCreator(String name, String creator); + + List findByNameOrCreator(String name, String creator); + + List findByNameAndCreatorOrForkCount(String name, String creator, Long forkCount); + + List findByNameOrCreatorAndForkCount(String name, String creator, Long forkCount); + + List findByNameOrCreatorOrForkCount(String name, String creator, Long forkCount); + + List findByNameOrCreatorAndForkCountOrStarCount(String name, String creator, + Long forkCount, Long starCount); + + List findByForkCountGreaterThan(Long forkCount); + + List findByCreatorAndForkCountGreaterThan(String creator, Long forkCount); + + List findByCreatorOrForkCountGreaterThan(String creator, Long forkCount); + + List findByNameOrCreator(String name, String creator, Sort sort); + + List findByNameAndCreator(String name, String creator, Sort sort); + + List findByForkCount(Long forkCount, Sort sort); + + List findByStarCountLessThan(Long starCount); + + List findByForkCountLessThanEqual(Long forkCount); + + List findByStarCountLessThanAndForkCountGreaterThan(Long max, Long min); + + List findByForkCountLessThanEqualAndStarCountGreaterThan(Long max, Long min); + + List findByStarCountGreaterThanEqual(Long count); + + List findByForkCountGreaterThanEqualAndCreator(Long count, String creator); + + List findByHasReleasedTrue(); + + List findByHasReleasedFalse(); + + List findByHasReleasedTrueAndCreator(String creator); + + List findByHasReleasedFalseAndCreator(String creator); + + List findByHasReleasedTrueOrCreator(String creator); + + List findByHasReleasedFalseOrCreator(String creator); + + List findByCreatorIn(Collection creators); + + List findByCreatorInAndStarCountIn(Collection creators, Collection starCounts); + + List findByCreatorNotIn(Collection creators); + + List findByCreatorInAndStarCountNotIn(Collection creators, Collection starCounts); + + List findByNameIsNull(); + + List findByNameIsNullAndForkCount(Long forkCount); + + List findByNameIsNotNull(); + + List findByNameIsNotNullAndHasReleased(boolean hasReleased); + + Page findByForkCount(Long forkCount, Pageable pageable); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java new file mode 100644 index 000000000000..0e27bd1381e0 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Question; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; + +public interface QuestionRepository extends CosmosRepository { +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java new file mode 100644 index 000000000000..6ad3a66ea4b4 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Course; +import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository; +import reactor.core.publisher.Flux; + +import java.util.Collection; + +public interface ReactiveCourseRepository extends ReactiveCosmosRepository { + + Flux findByDepartmentIn(Collection departments); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java new file mode 100644 index 000000000000..b6606d8fe59b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.SortedProject; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.List; + +public interface SortedProjectRepository extends CosmosRepository { + + List findByNameOrCreator(String name, String creator, Sort sort); + + List findByNameAndCreator(String name, String creator, Sort sort); + + List findByForkCount(Long forkCount, Sort sort); + + Page findByForkCount(Long forkCount, Pageable pageable); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java new file mode 100644 index 000000000000..295f881e24a6 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.inheritance.Square; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SquareRepository extends CosmosRepository { + +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java new file mode 100644 index 000000000000..4428770df373 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.repository; + +import com.microsoft.azure.spring.data.cosmosdb.domain.Student; +import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface StudentRepository extends CosmosRepository { + + List findByFirstNameContaining(String firstName); + + List findByFirstNameContainingAndLastNameContaining(String firstName, String lastName); + + List findByFirstNameEndsWith(String firstName); + + List findByFirstNameStartsWith(String firstName); + + List findByLastNameStartsWith(String lastName); + + List findByFirstNameStartsWithAndLastNameEndingWith(String firstName, String lastName); + + List findByFirstNameStartsWithOrLastNameContaining(String firstName, String lastName); + + List findByFirstNameNot(String firstName); + + List findByFirstNameContainingAndLastNameNot(String firstName, String lastName); + + Boolean existsByFirstName(String firstName); + + Boolean existsByLastNameContaining(String lastName); +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java new file mode 100644 index 000000000000..cf6f65928c96 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java @@ -0,0 +1,355 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import java.util.List; +import java.util.Objects; + +import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document; +import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; +import com.microsoft.azure.spring.data.cosmosdb.domain.Address; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import com.microsoft.azure.spring.data.cosmosdb.domain.Student; +import org.junit.Test; + +import org.springframework.data.annotation.Version; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CosmosEntityInformationUnitTest { + private static final String ID = "entity_info_test_id"; + private static final String FIRST_NAME = "first name"; + private static final String LAST_NAME = "last name"; + private static final List HOBBIES = TestConstants.HOBBIES; + private static final List
ADDRESSES = TestConstants.ADDRESSES; + + @Test + public void testGetId() { + final Person testPerson = new Person(ID, FIRST_NAME, LAST_NAME, HOBBIES, ADDRESSES); + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(Person.class); + + final String idField = entityInformation.getId(testPerson); + + assertThat(idField).isEqualTo(testPerson.getId()); + } + + @Test + public void testGetIdType() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(Person.class); + + final Class idType = entityInformation.getIdType(); + assertThat(idType.getSimpleName()).isEqualTo(String.class.getSimpleName()); + } + + @Test + public void testGetContainerName() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(Person.class); + + final String containerName = entityInformation.getContainerName(); + assertThat(containerName).isEqualTo(Person.class.getSimpleName()); + } + + @Test + public void testCustomContainerName() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(VersionedVolunteer.class); + + final String containerName = entityInformation.getContainerName(); + assertThat(containerName).isEqualTo("testCollection"); + } + + @Test + public void testGetPartitionKeyName() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(VolunteerWithPartitionKey.class); + + final String partitionKeyName = entityInformation.getPartitionKeyFieldName(); + assertThat(partitionKeyName).isEqualTo("name"); + } + + @Test + public void testNullPartitionKeyName() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(Volunteer.class); + + final String partitionKeyName = entityInformation.getPartitionKeyFieldName(); + assertThat(partitionKeyName).isEqualTo(null); + } + + @Test + public void testCustomPartitionKeyName() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation<>(VolunteerWithCustomPartitionKey.class); + + final String partitionKeyName = entityInformation.getPartitionKeyFieldName(); + assertThat(partitionKeyName).isEqualTo("vol_name"); + } + + @Test + public void testVersionedEntity() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(VersionedVolunteer.class); + + final boolean isVersioned = entityInformation.isVersioned(); + assertThat(isVersioned).isTrue(); + } + + @Test + public void testEntityShouldNotBeVersionedWithWrongType() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(WrongVersionType.class); + + final boolean isVersioned = entityInformation.isVersioned(); + assertThat(isVersioned).isFalse(); + } + + @Test + public void testEntityShouldNotBeVersionedWithoutAnnotationOnEtag() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(VersionOnWrongField.class); + + final boolean isVersioned = entityInformation.isVersioned(); + assertThat(isVersioned).isFalse(); + } + + @Test + public void testNonVersionedEntity() { + final CosmosEntityInformation entityInformation = + new CosmosEntityInformation(Student.class); + + final boolean isVersioned = entityInformation.isVersioned(); + assertThat(isVersioned).isFalse(); + } + + @Document(collection = "testCollection") + private static class Volunteer { + String id; + String name; + } + + @Document + private static class VolunteerWithCustomPartitionKey { + private String id; + @PartitionKey("vol_name") + private String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Document + private static class VolunteerWithPartitionKey { + private String id; + @PartitionKey + private String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Document(collection = "testCollection") + private static class VersionedVolunteer { + private String id; + private String name; + @Version + private String _etag; + + public VersionedVolunteer() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String get_etag() { + return _etag; + } + + public void set_etag(String _etag) { + this._etag = _etag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VersionedVolunteer that = (VersionedVolunteer) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name) && + Objects.equals(_etag, that._etag); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, _etag); + } + + @Override + public String toString() { + return "VersionedVolunteer{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", _etag='" + _etag + '\'' + + '}'; + } + } + + @Document + private static class WrongVersionType { + private String id; + private String name; + private long _etag; + + public WrongVersionType() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long get_etag() { + return _etag; + } + + public void set_etag(long _etag) { + this._etag = _etag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WrongVersionType that = (WrongVersionType) o; + return _etag == that._etag && + Objects.equals(id, that.id) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, _etag); + } + + @Override + public String toString() { + return "WrongVersionType{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", _etag=" + _etag + + '}'; + } + } + + @Document + private static class VersionOnWrongField { + private String id; + @Version + private String name; + private String _etag; + + public VersionOnWrongField() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String get_etag() { + return _etag; + } + + public void set_etag(String _etag) { + this._etag = _etag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VersionOnWrongField that = (VersionOnWrongField) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name) && + Objects.equals(_etag, that._etag); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, _etag); + } + + @Override + public String toString() { + return "VersionOnWrongField{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", _etag='" + _etag + '\'' + + '}'; + } + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java new file mode 100644 index 000000000000..a79f59787587 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.repository.repository.PersonRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(MockitoJUnitRunner.class) +public class CosmosRepositoryFactoryBeanUnitTest { + @Mock + CosmosTemplate dbTemplate; + + @Test + public void testCreateRepositoryFactory() { + final CosmosRepositoryFactoryBean factoryBean = + new CosmosRepositoryFactoryBean(PersonRepository.class); + final RepositoryFactorySupport factory = factoryBean.createRepositoryFactory(); + assertThat(factory).isNotNull(); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java new file mode 100644 index 000000000000..b9252c4ca758 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.azure.spring.data.cosmosdb.repository.support; + +import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate; +import com.microsoft.azure.spring.data.cosmosdb.domain.Person; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.repository.core.EntityInformation; + +import static org.junit.Assert.assertTrue; + +@RunWith(MockitoJUnitRunner.class) +public class CosmosRepositoryFactoryUnitTest { + + @Mock + CosmosTemplate dbTemplate; + + @Autowired + ApplicationContext applicationContext; + + @Test + public void useMappingCosmosDBEntityInfoIfMappingContextSet() { + final CosmosRepositoryFactory factory = new CosmosRepositoryFactory(dbTemplate, applicationContext); + final EntityInformation entityInfo = factory.getEntityInformation(Person.class); + assertTrue(entityInfo instanceof CosmosEntityInformation); + } +} diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties new file mode 100644 index 000000000000..85ff3ddb4a40 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties @@ -0,0 +1,15 @@ +cosmosdb.uri=${DOCUMENTDB_URI} +cosmosdb.key=${DOCUMENTDB_KEY} +cosmosdb.secondaryKey=${COSMOSDB_SECONDARY_KEY} + +#You can also use connection string instead of uri and key to connect to cosmos DB +#cosmosdb.connection-string=${DOCUMENTDB_CONNECTION_STRING} + +dynamic.collection.name=spel-property-collection +# Performance test configurations +perf.recursive.times=10 +perf.batch.size=3 +perf.acceptance.percentage=10 + +# Populate query metrics +cosmosdb.populateQueryMetrics=true diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml new file mode 100644 index 000000000000..0c17f1c5ef0b --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml @@ -0,0 +1,4 @@ +cosmosdb: + key: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== + uri: ${DOCUMENTDB_URI} + telemetryAllowed: false diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml new file mode 100644 index 000000000000..45f2eda3202c --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file From 1d6b0983644c7c0e4734c2a65fea35c0fdcfe93c Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Sun, 14 Jun 2020 17:10:02 +0800 Subject: [PATCH 05/17] modify for compiler errors --- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 107 ++++++++++-------- .../config/CosmosDBConfig.java | 27 ++++- .../core/CosmosTemplate.java | 2 +- .../core/ReactiveCosmosOperations.java | 4 +- .../core/ReactiveCosmosTemplate.java | 5 +- .../core/convert/MappingCosmosConverter.java | 4 +- .../core/mapping/PartitionKey.java | 2 +- .../core/query/CriteriaType.java | 18 +-- .../core/query/DocumentQuery.java | 2 +- .../repository/query/CosmosQueryCreator.java | 4 +- .../query/ReactiveCosmosQueryCreator.java | 4 +- .../support/SimpleCosmosRepository.java | 34 +++--- .../UserAgentTestIT.java | 4 +- .../common/ExpressionResolverUnitTest.java | 2 +- .../common/PageTestUtils.java | 4 +- .../common/TestConstants.java | 44 +++---- .../core/CosmosTemplateIllegalTest.java | 3 +- .../core/ReactiveCosmosTemplateIT.java | 3 +- .../BasicCosmosPersistentEntityUnitTest.java | 4 +- .../domain/Student.java | 30 +++-- .../CosmosRepositoryFactoryBeanUnitTest.java | 5 +- 21 files changed, 178 insertions(+), 134 deletions(-) diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index d19ff42775b3..9dbe14f1a4b1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -147,6 +147,12 @@ 1.2 + + + + + + org.mockito @@ -229,6 +235,7 @@ org.json:json:20140107 com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + org.slf4j:slf4j-simple:[1.7.25] @@ -262,34 +269,34 @@ - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.5 - - Max - Low - true - ${project.build.directory}/findbugs - - ${project.basedir}/config/findbugs-exclude.xml - - - - org.apache.ant - ant - 1.9.4 - - - - - compile - - check - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.codehaus.mojo cobertura-maven-plugin @@ -331,24 +338,32 @@ - - - - - - - - - - - - - - - - - - + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + private + false + + + com/microsoft/azure/spring/data/cosmosdb/core/mapping/BasicCosmosPersistentProperty.java + + + + + + attach-javadocs + + jar + + + true + none + + + + org.apache.maven.plugins maven-antrun-plugin diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java index f5d010a0b9fd..6bd052c0f1bd 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java @@ -209,12 +209,27 @@ public CosmosDBConfig build() { } public String toString() { - return "CosmosDBConfig.CosmosDBConfigBuilder(uri=" + this.uri + ", key=" + this.key - + ", database=" + this.database + ", connectionPolicy=" + this.connectionPolicy - + ", consistencyLevel=" + this.consistencyLevel + ", allowTelemetry=" + this.allowTelemetry - + ", requestOptions=" + this.requestOptions + ", cosmosKeyCredential=" + this.cosmosKeyCredential - + ", responseDiagnosticsProcessor=" + this.responseDiagnosticsProcessor + ", populateQueryMetrics=" - + this.populateQueryMetrics + ")"; + return "CosmosDBConfig.CosmosDBConfigBuilder(uri=" + + this.uri + + ", key=" + + this.key + + ", database=" + + this.database + + ", connectionPolicy=" + + this.connectionPolicy + + ", consistencyLevel=" + + this.consistencyLevel + + ", allowTelemetry=" + + this.allowTelemetry + + ", requestOptions=" + + this.requestOptions + + ", cosmosKeyCredential=" + + this.cosmosKeyCredential + + ", responseDiagnosticsProcessor=" + + this.responseDiagnosticsProcessor + + ", populateQueryMetrics=" + + this.populateQueryMetrics + + ")"; } } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java index e583e987a67d..8f539004e1e7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java @@ -381,7 +381,7 @@ public Boolean exists(@NonNull DocumentQuery query, @NonNull Class domain * @param query The representation for query method. * @param domainType Class of domain * @param containerName Container name of database - * @param + * @param class of domainType * @return All the deleted items as List. */ @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java index 152ef6a60800..e54d3d4513b2 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java @@ -21,9 +21,9 @@ public interface ReactiveCosmosOperations { * @return Mono of cosmos container response */ @Deprecated - Mono createCollectionIfNotExists(CosmosEntityInformation information); + Mono createCollectionIfNotExists(CosmosEntityInformation information); - Mono createContainerIfNotExists(CosmosEntityInformation information); + Mono createContainerIfNotExists(CosmosEntityInformation information); Flux findAll(String containerName, Class domainType); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java index 99b207397e1a..e5639ec799b0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java @@ -95,7 +95,7 @@ public void setApplicationContext(@NonNull ApplicationContext applicationContext * @return Mono containing CosmosContainerResponse */ @Override - public Mono createCollectionIfNotExists(CosmosEntityInformation information) { + public Mono createCollectionIfNotExists(CosmosEntityInformation information) { return createContainerIfNotExists(information); } @@ -106,7 +106,7 @@ public Mono createCollectionIfNotExists(CosmosEntityInf * @return Mono containing CosmosContainerResponse */ @Override - public Mono createContainerIfNotExists(CosmosEntityInformation information) { + public Mono createContainerIfNotExists(CosmosEntityInformation information) { return cosmosClient .createDatabaseIfNotExists(this.databaseName) @@ -279,6 +279,7 @@ public Mono insert(T objectToSave, PartitionKey partitionKey) { * Insert * * @param objectToSave the object to save + * @param type of inserted objectToSave * @return Mono with the item or error */ public Mono insert(T objectToSave) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java index ef99a8abaf8d..6ce4fba3c2e7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java @@ -152,8 +152,8 @@ private ConvertingPropertyAccessor getPropertyAccessor(Object entity) { /** * Convert a property value to the value stored in CosmosDB * - * @param fromPropertyValue - * @return + * @param fromPropertyValue source property value + * @return fromPropertyValue converted property value stored in CosmosDB */ public static Object toCosmosDbValue(Object fromPropertyValue) { if (fromPropertyValue == null) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java index 54281da598c6..409a80317ca4 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java @@ -12,7 +12,7 @@ /** * The name of the partition key if the serialized attribute name differs from the field name * - * @return + * @return partition key name */ String value() default ""; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java index 35562acab43d..96126b6fdbe3 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java @@ -78,7 +78,7 @@ public String getSqlKeyword() { /** * Check if PartType is NOT supported. * - * @param partType + * @param partType PartType to be checked. * @return True if unsupported, or false. */ public static boolean isPartTypeUnSupported(@NonNull Part.Type partType) { @@ -88,7 +88,7 @@ public static boolean isPartTypeUnSupported(@NonNull Part.Type partType) { /** * Check if PartType is supported. * - * @param partType + * @param partType PartType to be checked. * @return True if supported, or false. */ public static boolean isPartTypeSupported(@NonNull Part.Type partType) { @@ -106,10 +106,10 @@ public static CriteriaType toCriteriaType(@NonNull Part.Type partType) { } /** - * Check if CriteriaType operation is closure, with format of (A ops A -> A). + * Check if CriteriaType operation is closure, with format of (A ops A -> A). * Example: AND, OR. * - * @param type + * @param type CriteriaType operation * @return True if match, or false. */ public static boolean isClosed(CriteriaType type) { @@ -123,10 +123,10 @@ public static boolean isClosed(CriteriaType type) { } /** - * Check if CriteriaType operation is binary, with format of (A ops A -> B). + * Check if CriteriaType operation is binary, with format of (A ops A -> B). * Example: IS_EQUAL, AFTER. * - * @param type + * @param type CriteriaType operation * @return True if match, or false. */ public static boolean isBinary(CriteriaType type) { @@ -155,7 +155,7 @@ public static boolean isBinary(CriteriaType type) { /** * Check if CriteriaType operation is a function. * - * @param type + * @param type CriteriaType * @return True if match, or false. */ public static boolean isFunction(CriteriaType type) { @@ -172,9 +172,9 @@ public static boolean isFunction(CriteriaType type) { } /** - * Check if CriteriaType operation is unary, with format of (ops A -> B). + * Check if CriteriaType operation is unary, with format of (ops A -> B). * - * @param type + * @param type CriteriaType * @return True if match, or false. */ public static boolean isUnary(CriteriaType type) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java index 55cdf70a5978..6927e81b4dc4 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java @@ -69,7 +69,7 @@ private boolean hasKeywordOr() { * Indicate if DocumentQuery should enable cross partition query. * * @param partitionKeys The list of partitionKey names. - * @return + * @return If DocumentQuery should enable cross partition query */ public boolean isCrossPartitionQuery(@NonNull List partitionKeys) { if (partitionKeys.isEmpty()) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java index df8fb6007d82..f9bbf1133a98 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java @@ -38,8 +38,8 @@ private String getSubject(@NonNull Part part) { String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath(); final Class domainType = part.getProperty().getOwningType().getType(); - @SuppressWarnings("unchecked") final CosmosEntityInformation information = - new CosmosEntityInformation(domainType); + @SuppressWarnings("unchecked") final CosmosEntityInformation information = + new CosmosEntityInformation<>(domainType); if (information.getIdField().getName().equals(subject)) { subject = Constants.ID_PROPERTY_NAME; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java index 66e46954db8b..342ec58e6f60 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java @@ -35,8 +35,8 @@ private String getSubject(@NonNull Part part) { String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath(); final Class domainType = part.getProperty().getOwningType().getType(); - @SuppressWarnings("unchecked") final CosmosEntityInformation information = - new CosmosEntityInformation(domainType); + @SuppressWarnings("unchecked") final CosmosEntityInformation information = + new CosmosEntityInformation<>(domainType); if (information.getIdField().getName().equals(subject)) { subject = Constants.ID_PROPERTY_NAME; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java index b87b5e5d6c46..c821f87fac86 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java @@ -57,7 +57,7 @@ private CosmosContainerProperties createContainerIfNotExists() { * save entity without partition * * @param entity to be saved - * @param + * @param type of entity * @return entity */ @Override @@ -86,9 +86,9 @@ private PartitionKey createKey(String partitionKeyValue) { /** * batch save entities * - * @param entities - * @param - * @return + * @param entities Batch entities + * @param type of entities + * @return return the saved entities */ @Override public Iterable saveAll(Iterable entities) { @@ -106,7 +106,7 @@ public Iterable saveAll(Iterable entities) { /** * find all entities from one container without configuring partition key value * - * @return + * @return return Iterable of the found entities List */ @Override public Iterable findAll() { @@ -116,8 +116,8 @@ public Iterable findAll() { /** * find entities based on id list from one container without partitions * - * @param ids - * @return + * @param ids id list used to find entities + * @return return a List of all found entities */ @Override public List findAllById(Iterable ids) { @@ -129,8 +129,8 @@ public List findAllById(Iterable ids) { /** * find one entity per id without partitions * - * @param id - * @return + * @param id an id used to find entity + * @return return the searching result */ @Override public Optional findById(ID id) { @@ -157,7 +157,7 @@ public Optional findById(ID id, PartitionKey partitionKey) { /** * return count of documents in one container without partitions * - * @return + * @return count of documents in one container without partitions */ @Override public long count() { @@ -167,7 +167,7 @@ public long count() { /** * delete one document per id without configuring partition key value * - * @param id + * @param id an id used to specify the deleted document */ @Override public void deleteById(ID id) { @@ -187,7 +187,7 @@ public void deleteById(ID id, PartitionKey partitionKey) { /** * delete one document per entity * - * @param entity + * @param entity the entity used to specify a document */ @Override public void delete(T entity) { @@ -211,7 +211,7 @@ public void deleteAll() { /** * delete list of entities without partitions * - * @param entities + * @param entities list of entities to be deleted */ @Override public void deleteAll(Iterable entities) { @@ -223,8 +223,8 @@ public void deleteAll(Iterable entities) { /** * check if an entity exists per id without partition * - * @param primaryKey - * @return + * @param primaryKey an id to specify an entity + * @return if the entity exists */ @Override public boolean existsById(ID primaryKey) { @@ -236,7 +236,7 @@ public boolean existsById(ID primaryKey) { /** * Returns all entities sorted by the given options. * - * @param sort + * @param sort the Sort option for queries. * @return all entities sorted by the given options */ @Override @@ -251,7 +251,7 @@ public Iterable findAll(@NonNull Sort sort) { * FindQuerySpecGenerator * Returns a Page of entities meeting the paging restriction provided in the Pageable object. * - * @param pageable + * @param pageable the Pageable object providing paging restriction * @return a page of entities */ @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java index b05d69425065..3714460b8996 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java @@ -16,8 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; -@Ignore("Cannot use fake uri and key with CosmosDbFactory as it tries the connection on new creation." + - "At the same time, cannot use mockito with real values, because it won't prepare PropertyLoader class for mocking") +@Ignore("Cannot use fake uri and key with CosmosDbFactory as it tries the connection on new creation." + + "At the same time, cannot use mockito with real values, because it won't prepare PropertyLoader class for mocking") @RunWith(PowerMockRunner.class) @PrepareForTest(PropertyLoader.class) @PropertySource(value = {"classpath:application.properties"}) diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java index 96f5177ca67f..ccb3160225ca 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java @@ -42,7 +42,7 @@ public void testExpressionsShouldBeResolved() { static class TestConfiguration { @Bean public ExpressionResolver expressionResolver(ConfigurableBeanFactory beanFactory) { - return new ExpressionResolver((ConfigurableBeanFactory) beanFactory); + return new ExpressionResolver(beanFactory); } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java index 703465594920..193369f5978e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java @@ -11,7 +11,7 @@ import static org.junit.Assert.assertTrue; public class PageTestUtils { - public static void validateLastPage(Page page, int pageSize) { + public static void validateLastPage(Page page, int pageSize) { final Pageable pageable = page.getPageable(); assertThat(pageable).isInstanceOf(CosmosPageRequest.class); @@ -19,7 +19,7 @@ public static void validateLastPage(Page page, int pageSize) { assertThat(pageable.getPageSize()).isEqualTo(pageSize); } - public static void validateNonLastPage(Page page, int pageSize) { + public static void validateNonLastPage(Page page, int pageSize) { final Pageable pageable = page.getPageable(); assertThat(pageable).isInstanceOf(CosmosPageRequest.class); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java index 5a31b42160b6..d9a39f04818f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java @@ -35,21 +35,21 @@ public class TestConstants { public static final int TIME_TO_LIVE = 5; public static final boolean INDEXINGPOLICY_AUTOMATIC = false; public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.LAZY; - public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," + - "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," + - "{\"kind\":\"Spatial\",\"dataType\":\"Point\"}" + - "]}"; - public static final String INCLUDEDPATH_1 = "{\"path\":\"/cache/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":3}," + - "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}," + - "{\"kind\":\"Spatial\",\"dataType\":\"LineString\"}" + - "]}"; - public static final String INCLUDEDPATH_2 = "{\"path\":\"/entities/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":4}," + - "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":4}," + - "{\"kind\":\"Spatial\",\"dataType\":\"Polygon\"}" + - "]}"; + public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Point\"}" + + "]}"; + public static final String INCLUDEDPATH_1 = "{\"path\":\"/cache/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":3}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}," + + "{\"kind\":\"Spatial\",\"dataType\":\"LineString\"}" + + "]}"; + public static final String INCLUDEDPATH_2 = "{\"path\":\"/entities/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":4}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":4}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Polygon\"}" + + "]}"; public static final String[] INCLUDEDPATHS = { INCLUDEDPATH_0, INCLUDEDPATH_1, @@ -62,15 +62,15 @@ public class TestConstants { EXCLUDEDPATH_1, }; - public static final String ORDER_BY_STRING_PATH = "{\"path\":\"/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1}," + - "]}"; + public static final String ORDER_BY_STRING_PATH = "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1}," + + "]}"; public static final String STARTSWITH_INCLUDEDPATH = - "{\"path\":\"/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + - "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":3}" + - "]}"; + "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":3}" + + "]}"; public static final String[] PERSON_INCLUDEDPATHS = { STARTSWITH_INCLUDEDPATH diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java index d75736206211..0c63ef1c49e9 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import java.util.Arrays; +@SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class CosmosTemplateIllegalTest { private static final String NULL_STR = null; @@ -33,7 +34,7 @@ public class CosmosTemplateIllegalTest { @Mock(answer = Answers.CALLS_REAL_METHODS) private CosmosTemplate dbTemplate; - private Class dbTemplateClass; + private Class dbTemplateClass; @Before public void setUp() { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java index 0dc32b6026d0..37395f876c36 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java @@ -46,6 +46,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.fail; +@SuppressWarnings("unchecked") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = TestRepositoryConfig.class) public class ReactiveCosmosTemplateIT { @@ -127,7 +128,7 @@ public static void afterClassCleanup() { public void testInsertDuplicateId() { final Mono insertMono = cosmosTemplate.insert(TEST_PERSON, new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); - final TestSubscriber testSubscriber = new TestSubscriber(); + final TestSubscriber testSubscriber = new TestSubscriber<>(); insertMono.subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); testSubscriber.assertNotComplete(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java index e86cf45b4e9c..8c5282ff1a1f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java @@ -13,14 +13,14 @@ public class BasicCosmosPersistentEntityUnitTest { @Test public void testGetCollection() { - final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( + final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( ClassTypeInformation.from(Person.class)); assertThat(entity.getContainer()).isEqualTo(""); } @Test public void testGetLanguage() { - final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( + final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity( ClassTypeInformation.from(Person.class)); assertThat(entity.getLanguage()).isEqualTo(""); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java index dd30806ceb58..6e8057275916 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java @@ -46,12 +46,16 @@ public void setLastName(String lastName) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Student student = (Student) o; - return Objects.equals(id, student.id) && - Objects.equals(firstName, student.firstName) && - Objects.equals(lastName, student.lastName); + return Objects.equals(id, student.id) + && Objects.equals(firstName, student.firstName) + && Objects.equals(lastName, student.lastName); } @Override @@ -61,10 +65,16 @@ public int hashCode() { @Override public String toString() { - return "Student{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - '}'; + return "Student{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java index a79f59787587..e6bbdcaf5787 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java @@ -12,6 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; +@SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class CosmosRepositoryFactoryBeanUnitTest { @Mock @@ -19,8 +20,8 @@ public class CosmosRepositoryFactoryBeanUnitTest { @Test public void testCreateRepositoryFactory() { - final CosmosRepositoryFactoryBean factoryBean = - new CosmosRepositoryFactoryBean(PersonRepository.class); + final CosmosRepositoryFactoryBean factoryBean = + new CosmosRepositoryFactoryBean<>(PersonRepository.class); final RepositoryFactorySupport factory = factoryBean.createRepositoryFactory(); assertThat(factory).isNotNull(); } From d4fd2df0e7fb9defebf14961cd3dbd98b92b0799 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Sun, 14 Jun 2020 19:24:50 +0800 Subject: [PATCH 06/17] modify for checkstyle errors --- .../checkstyle/checkstyle-suppressions.xml | 13 + eng/versioning/external_dependencies.txt | 8 +- .../config/findbugs-exclude.xml | 13 - sdk/spring/azure-spring-data-cosmosdb/pom.xml | 701 ++++++------------ .../Constants.java | 5 +- .../CosmosDbFactory.java | 23 + .../common/CosmosdbUtils.java | 28 +- .../common/ExpressionResolver.java | 4 + .../common/MacAddress.java | 14 +- .../common/Memoizer.java | 13 +- .../common/PropertyLoader.java | 20 +- .../common/TelemetryEventData.java | 38 +- .../common/TelemetrySender.java | 23 +- .../common/package-info.java | 7 + .../config/AbstractCosmosConfiguration.java | 35 + .../config/CosmosConfigurationSupport.java | 24 + .../config/CosmosDBConfig.java | 172 ++++- .../config/package-info.java | 7 + .../core/CosmosOperations.java | 191 +++++ .../core/CosmosTemplate.java | 157 +++- .../core/ReactiveCosmosOperations.java | 173 ++++- .../core/ReactiveCosmosTemplate.java | 93 ++- .../core/ResponseDiagnostics.java | 68 +- .../core/ResponseDiagnosticsProcessor.java | 3 + .../core/convert/MappingCosmosConverter.java | 41 +- .../core/convert/ObjectMapperFactory.java | 7 + .../core/convert/package-info.java | 7 + .../generator/AbstractQueryGenerator.java | 26 +- .../core/generator/CountQueryGenerator.java | 3 + .../generator/FindQuerySpecGenerator.java | 7 +- .../core/generator/QuerySpecGenerator.java | 3 + .../core/generator/package-info.java | 7 + .../mapping/BasicCosmosPersistentEntity.java | 18 +- .../BasicCosmosPersistentProperty.java | 11 +- .../core/mapping/CosmosMappingContext.java | 5 +- .../core/mapping/CosmosPersistentEntity.java | 18 +- .../mapping/CosmosPersistentProperty.java | 4 +- .../core/mapping/Document.java | 26 +- .../core/mapping/DocumentIndexingPolicy.java | 26 +- .../core/mapping/PartitionKey.java | 9 +- .../core/mapping/package-info.java | 7 + .../core/package-info.java | 8 + .../core/query/CosmosPageImpl.java | 23 +- .../core/query/CosmosPageRequest.java | 55 +- .../core/query/Criteria.java | 47 +- .../core/query/CriteriaType.java | 25 +- .../core/query/DocumentQuery.java | 47 +- .../core/query/package-info.java | 7 + .../exception/ConfigurationException.java | 14 + .../exception/CosmosDBAccessException.java | 21 + .../exception/CosmosDBExceptionUtils.java | 20 + .../exception/DatabaseCreationException.java | 15 + .../exception/IllegalCollectionException.java | 15 + .../exception/IllegalQueryException.java | 15 + .../exception/package-info.java | 7 + .../package-info.java | 7 + .../repository/CosmosRepository.java | 6 + .../repository/ReactiveCosmosRepository.java | 4 +- .../config/CosmosRepositoriesRegistrar.java | 4 +- ...osmosRepositoryConfigurationExtension.java | 9 +- .../config/EnableCosmosRepositories.java | 57 +- .../EnableReactiveCosmosRepositories.java | 48 +- .../ReactiveCosmosRepositoriesRegistrar.java | 4 +- ...osmosRepositoryConfigurationExtension.java | 9 +- .../repository/config/package-info.java | 7 + .../repository/package-info.java | 7 + .../repository/query/AbstractCosmosQuery.java | 20 + .../query/AbstractReactiveCosmosQuery.java | 24 +- .../query/CosmosEntityMetadata.java | 12 +- .../repository/query/CosmosParameter.java | 8 + .../query/CosmosParameterAccessor.java | 9 + .../CosmosParameterParameterAccessor.java | 9 + .../repository/query/CosmosParameters.java | 8 + .../repository/query/CosmosQueryCreator.java | 21 +- .../query/CosmosQueryExecution.java | 34 +- .../repository/query/CosmosQueryMethod.java | 13 +- .../repository/query/PartTreeCosmosQuery.java | 10 + .../query/PartTreeReactiveCosmosQuery.java | 10 + .../query/ReactiveCosmosEntityMetadata.java | 13 + .../ReactiveCosmosParameterAccessor.java | 9 + ...ctiveCosmosParameterParameterAccessor.java | 10 + .../query/ReactiveCosmosQueryCreator.java | 14 +- .../query/ReactiveCosmosQueryExecution.java | 24 + .../query/ReactiveCosmosQueryMethod.java | 13 +- .../query/SimpleCosmosEntityMetadata.java | 24 + .../SimpleReactiveCosmosEntityMetadata.java | 19 + .../repository/query/package-info.java | 7 + .../support/CosmosEntityInformation.java | 98 ++- .../support/CosmosRepositoryFactory.java | 12 +- .../support/CosmosRepositoryFactoryBean.java | 17 +- .../ReactiveCosmosRepositoryFactory.java | 11 +- .../ReactiveCosmosRepositoryFactoryBean.java | 15 + .../support/SimpleCosmosRepository.java | 21 +- .../SimpleReactiveCosmosRepository.java | 15 + .../repository/support/package-info.java | 7 + .../CosmosDbFactoryTestIT.java | 17 +- .../UserAgentTestIT.java | 2 +- .../common/MemoizerUnitTest.java | 4 +- .../common/TestConstants.java | 50 +- .../common/TestUtils.java | 2 +- .../config/AbstractCosmosConfigurationIT.java | 4 +- .../core/CosmosTemplateIT.java | 4 +- .../core/CosmosTemplatePartitionIT.java | 7 +- .../core/CosmosTemplateUnitTest.java | 2 +- .../domain/Address.java | 7 +- .../domain/Contact.java | 12 +- .../domain/Course.java | 14 +- .../domain/Customer.java | 51 +- .../domain/IntegerIdDomain.java | 23 +- .../domain/Memo.java | 34 +- .../domain/NoDBAnnotationPerson.java | 40 +- .../domain/PageableAddress.java | 22 +- .../domain/PageableMemo.java | 34 +- .../domain/PageablePerson.java | 44 +- .../domain/PartitionPerson.java | 40 +- .../domain/Person.java | 44 +- .../domain/Project.java | 45 +- .../domain/Question.java | 24 +- .../domain/Role.java | 30 +- .../domain/SortedProject.java | 45 +- .../domain/SpELBeanStudent.java | 30 +- .../domain/SpELPropertyStudent.java | 30 +- .../domain/inheritance/Shape.java | 13 +- .../domain/inheritance/Square.java | 24 +- .../performance/PerfConfiguration.java | 2 +- .../performance/PerformanceReport.java | 34 +- .../performance/domain/PerfPerson.java | 24 +- .../performance/service/SdkService.java | 12 +- .../performance/utils/DatabaseUtils.java | 2 +- .../repository/TestRepositoryConfig.java | 7 +- .../IntegerIdDomainRepositoryIT.java | 25 +- .../integration/SpELCosmosDBAnnotationIT.java | 26 +- .../repository/PageableAddressRepository.java | 2 +- .../CosmosEntityInformationUnitTest.java | 95 ++- 134 files changed, 2961 insertions(+), 1012 deletions(-) delete mode 100644 sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java create mode 100644 sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml index 886abb829987..36a491991c0a 100755 --- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -457,6 +457,14 @@ + + + + + @@ -464,4 +472,9 @@ + + + + + diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index f58e0a29460d..bf6440512b57 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -272,12 +272,10 @@ spring_com.microsoft.azure:azure;1.34.0 spring_org.springframework:spring-web;5.2.6.RELEASE spring_com.microsoft.azure:azure-cosmos;3.7.3 spring_com.fasterxml.jackson.datatype:jackson-datatype-jsr310;2.10.0 -spring_org.mockito:mockito-core;2.8.9 -spring_org.powermock:powermock-module-junit4;1.7.1 +#spring_org.mockito:mockito-core;2.8.9 +#spring_org.powermock:powermock-module-junit4;1.7.1 spring_org.powermock:powermock-api-mockito2;1.7.1 spring_org.springframework.boot:spring-boot-starter-test;2.3.0.RELEASE spring_io.projectreactor:reactor-test;3.3.0.RELEASE spring_com.google.code.gson:gson;2.8.4 -spring_org.apache.maven.plugins:maven-surefire-plugin;2.12.4 -spring_org.apache.maven.plugins:maven-help-plugin;3.1.0 -spring_org.apache.maven.plugins:maven-source-plugin;2.2.1 + diff --git a/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml b/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml deleted file mode 100644 index 6a89562b9ca1..000000000000 --- a/sdk/spring/azure-spring-data-cosmosdb/config/findbugs-exclude.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 9dbe14f1a4b1..4cd0da038687 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -2,7 +2,7 @@ - 4.0.0 + 4.0.0 com.azure azure-client-sdk-parent @@ -10,498 +10,251 @@ ../../parents/azure-client-sdk-parent - com.microsoft.azure - spring-data-cosmosdb - 2.3.1-SNAPSHOT + com.microsoft.azure + spring-data-cosmosdb + 2.3.1-SNAPSHOT - Spring Data for Azure Cosmos DB SQL API - Spring Data for Azure Cosmos DB SQL API - https://github.com/Microsoft/spring-data-cosmosdb + Spring Data for Azure Cosmos DB SQL API + Spring Data for Azure Cosmos DB SQL API + https://github.com/Microsoft/spring-data-cosmosdb - - - MIT - https://github.com/Microsoft/spring-data-cosmosdb/blob/master/LICENSE - repo - - + + MM-dd-HH-mm-ss - - - yungez - Yunge Zhu - yungez@microsoft.com - - + spring-data-cosmosdb-test + testdb-${maven.build.timestamp} + true + false + false + - - Microsoft - https://www.microsoft.com - + + + org.springframework + spring-core + 5.2.6.RELEASE + + + commons-logging + commons-logging + + + - - scm:git:git://github.com/Microsoft/spring-data-cosmosdb.git - scm:git:ssh://github.com:Microsoft/spring-data-cosmosdb.git - - https://github.com/Microsoft/spring-data-cosmosdb/tree/master - - - 1.8 - 1.8 - UTF-8 - MM-dd-HH-mm-ss + + org.springframework + spring-web + 5.2.6.RELEASE + - spring-data-cosmosdb-test - testdb-${maven.build.timestamp} - false - false - false - + + org.springframework + spring-beans + 5.2.6.RELEASE + - - - spring-milestone - Spring Milestones - https://repo.spring.io/libs-milestone - - + + org.springframework + spring-context + 5.2.6.RELEASE + - - - org.springframework - spring-core - 5.2.6.RELEASE - - - commons-logging - commons-logging - - - + + org.springframework + spring-tx + 5.2.6.RELEASE + - - org.springframework - spring-web - 5.2.6.RELEASE - + + org.springframework.data + spring-data-commons + 2.3.0.RELEASE + - - org.springframework - spring-beans - 5.2.6.RELEASE - + + org.springframework + spring-expression + 5.2.6.RELEASE + + + com.microsoft.azure + azure-cosmos + 3.7.3 + - - org.springframework - spring-context - 5.2.6.RELEASE - + + com.fasterxml.jackson.module + jackson-module-parameter-names + 2.10.0 + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + 2.10.0 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.10.0 + + + org.json + json + 20140107 + - - org.springframework - spring-tx - 5.2.6.RELEASE - + + org.javatuples + javatuples + 1.2 + - - org.springframework.data - spring-data-commons - 2.3.0.RELEASE - + + + org.mockito + mockito-core + 2.8.9 + test + + + org.powermock + powermock-module-junit4 + 1.7.1 + test + + + org.powermock + powermock-api-mockito2 + 1.7.1 + test + + + org.springframework.boot + spring-boot-starter-test + 2.3.0.RELEASE + test + + + com.vaadin.external.google + android-json + + + - - org.springframework - spring-expression - 5.2.6.RELEASE - - - com.microsoft.azure - azure-cosmos - 3.7.3 - + + io.projectreactor + reactor-test + 3.3.0.RELEASE + test + - - com.fasterxml.jackson.module - jackson-module-parameter-names - 2.10.0 - - - com.fasterxml.jackson.datatype - jackson-datatype-jdk8 - 2.10.0 - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - 2.10.0 - - - org.json - json - 20140107 - + + org.slf4j + slf4j-simple + 1.7.25 + test + - - org.javatuples - javatuples - 1.2 - + + com.google.code.gson + gson + 2.8.4 + test + + - - - - - + + + + src/main/resources + true + + META-INF/project.properties + telemetry.config + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + + org.springframework:*:5.2.6.RELEASE + org.springframework.data:spring-data-commons:2.3.0.RELEASE + com.microsoft.azure:azure-cosmos:3.7.3 + org.javatuples:javatuples:1.2 + com.fasterxml.jackson.datatype:*:2.10.0 + org.json:json:20140107 + com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + org.slf4j:slf4j-simple:[1.7.25] + + + + + - - - org.mockito - mockito-core - 2.8.9 - test - - - org.powermock - powermock-module-junit4 - 1.7.1 - test - - - org.powermock - powermock-api-mockito2 - 1.7.1 - test - - - org.springframework.boot - spring-boot-starter-test - 2.3.0.RELEASE - test - - - com.vaadin.external.google - android-json - - - + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + true + 65 + 65 + + + + com/microsoft/azure/**/GetHashMac.class + com/microsoft/azure/**/Constants.class + + + + - - io.projectreactor - reactor-test - 3.3.0.RELEASE - test - + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.0 + + src/test/resources/application.properties + ${skip.integration.tests} + + + + integration-test + + integration-test + verify + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + private + + + BasicCosmosPersistentProperty.java + + + ${basedir}/src/main/java/com/microsoft/azure/spring/data/cosmosdb/core/mapping/ + + - - org.slf4j - slf4j-simple - 1.7.25 - test - + + - - com.google.code.gson - gson - 2.8.4 - test - - - - - - - src/main/resources - true - - META-INF/project.properties - telemetry.config - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M3 - - - - - org.springframework:*:5.2.6.RELEASE - org.springframework.data:spring-data-commons:2.3.0.RELEASE - com.microsoft.azure:azure-cosmos:3.7.3 - org.javatuples:javatuples:1.2 - com.fasterxml.jackson.datatype:*:2.10.0 - org.json:json:20140107 - com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 - com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 - org.slf4j:slf4j-simple:[1.7.25] - - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-help-plugin - 3.1.0 - - - show-profiles - compile - - active-profiles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - html - xml - - - true - 65 - 65 - - - - com/microsoft/azure/**/GetHashMac.class - com/microsoft/azure/**/Constants.class - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.22.0 - - src/test/resources/application.properties - ${skip.integration.tests} - - - - integration-test - - integration-test - verify - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - private - false - - - com/microsoft/azure/spring/data/cosmosdb/core/mapping/BasicCosmosPersistentProperty.java - - - - - - attach-javadocs - - jar - - - true - none - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - setup - pre-integration-test - - run - - - - - - - - - - - cleanup - post-integration-test - - run - - - - - - - - - - - - - - - dev - - true - - - dev - true - false - false - - - - integration-test-azure - - integration-test-azure - false - true - false - - - - travis-ci-test - - travis-ci-test - false - true - false - - - - performance-test - - performance-test - false - false - false - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.12.4 - - true - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.22.0 - - - PerformanceCompare.java - - - - - - - - integration-test-emulator - - integration-test-emulator - false - false - true - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.22.0 - - - - **/PageablePersonRepositoryIT.java - - - - - - - - release - - - release - - - - - doclint-java8-disable - - [1.8,) - - - -Xdoclint:none - - - diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java index 0224180f4032..63001bddc981 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java @@ -4,7 +4,10 @@ import com.azure.data.cosmos.IndexingMode; -public class Constants { +/** + * Constants class of CosmosDB properties + */ +public final class Constants { public static final String DEFAULT_COLLECTION_NAME = ""; public static final String DEFAULT_REQUEST_UNIT = "4000"; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java index bc5c83c48a4f..20ca21753504 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java @@ -17,6 +17,9 @@ import javax.annotation.PostConstruct; +/** + * Factory class for cosmosdb to create client + */ public class CosmosDbFactory { private final CosmosDBConfig config; @@ -35,12 +38,22 @@ private String getUserAgentSuffix() { return suffix; } + /** + * Validate config and initialization + * + * @param config cosmosdb config + */ public CosmosDbFactory(@NonNull CosmosDBConfig config) { validateConfig(config); this.config = config; } + /** + * To create a CosmosClient + * + * @return CosmosClient + */ public CosmosClient getCosmosClient() { final ConnectionPolicy policy = config.getConnectionPolicy(); final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix(); @@ -55,6 +68,11 @@ public CosmosClient getCosmosClient() { .build(); } + /** + * To create a CosmosSyncClient + * + * @return CosmosSyncClient + */ public CosmosSyncClient getCosmosSyncClient() { final ConnectionPolicy policy = config.getConnectionPolicy(); final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix(); @@ -91,6 +109,11 @@ private void sendTelemetry() { } } + /** + * To get config object of cosmosdb + * + * @return CosmosDBConfig + */ public CosmosDBConfig getConfig() { return config; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java index dac7ec510999..446a67539437 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java @@ -18,10 +18,20 @@ import java.io.IOException; +/** + * Util class to fill and process response diagnostics + */ public class CosmosdbUtils { private static final Logger LOGGER = LoggerFactory.getLogger(CosmosdbUtils.class); + /** + * Get a copy of an existing instance + * @param instance the known instance + * @param type of instance + * @return copy instance + * @throws ConfigurationException if the class type is invalid + */ @SuppressWarnings("unchecked") public static T getCopyFrom(@NonNull T instance) { final ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); @@ -30,10 +40,20 @@ public static T getCopyFrom(@NonNull T instance) { final String s = mapper.writeValueAsString(instance); return (T) mapper.readValue(s, instance.getClass()); } catch (IOException e) { - throw new ConfigurationException("failed to get copy from " + instance.getClass().getName(), e); + throw new ConfigurationException("failed to get copy from " + + instance.getClass().getName(), e); } } + /** + * Generate ResponseDiagnostics with cosmos and feed response diagnostics + * + * @param type of cosmosResponse + * @param responseDiagnosticsProcessor collect Response Diagnostics from API responses and + * then set in {@link ResponseDiagnostics} object. + * @param cosmosResponse response from cosmos + * @param feedResponse response from feed + */ public static void fillAndProcessResponseDiagnostics( ResponseDiagnosticsProcessor responseDiagnosticsProcessor, CosmosResponse cosmosResponse, FeedResponse feedResponse) { @@ -50,9 +70,9 @@ public static void fillAndProcessResponseDiagnostics( feedResponseDiagnostics = feedResponse.feedResponseDiagnostics(); cosmosResponseStatistics = new ResponseDiagnostics.CosmosResponseStatistics(feedResponse); } - if (cosmosResponseDiagnostics == null && - (feedResponseDiagnostics == null || feedResponseDiagnostics.toString().isEmpty()) && - cosmosResponseStatistics == null) { + if (cosmosResponseDiagnostics == null + && (feedResponseDiagnostics == null || feedResponseDiagnostics.toString().isEmpty()) + && cosmosResponseStatistics == null) { LOGGER.debug("Empty response diagnostics"); return; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java index 2df771685b19..c992ae5eaa4a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java @@ -16,6 +16,10 @@ public class ExpressionResolver { private static EmbeddedValueResolver embeddedValueResolver; + /** + * Initialize ExpressionResolver with ConfigurableBeanFactory + * @param beanFactory used to initialize the embeddedValueResolver + */ public ExpressionResolver(BeanFactory beanFactory) { if (beanFactory instanceof ConfigurableBeanFactory) { setEmbeddedValueResolver(new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory)); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java index 90411d5ce4fb..9db4d22a09ef 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java @@ -26,7 +26,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class MacAddress { +/** + * Mac address class to transfer mac address to hash mac address. + */ +public final class MacAddress { private static final String UNKNOWN_MAC_ADDRESS = "Unknown-Mac-Address"; private static final String MAC_REGEX = "([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}"; @@ -49,7 +52,9 @@ private static String getRawMac() { final String os = System.getProperty("os.name"); final StringBuilder macBuilder = new StringBuilder(); - if (os != null && !os.isEmpty() && os.toLowerCase(Locale.US).startsWith("win")) { + if (os != null + && !os.isEmpty() + && os.toLowerCase(Locale.US).startsWith("win")) { commands = Collections.singletonList("getmac"); } else { commands = Arrays.asList("ifconfig", "-a"); @@ -113,6 +118,11 @@ private static String hash(@NonNull String mac) { return builder.toString(); } + /** + * To get a hash Mac address. + * + * @return String Hash mac address + */ public static String getHashMac() { final String rawMac = getRawMac(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java index f0af790208d3..ce3530647e72 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java @@ -9,12 +9,21 @@ /** * Memoize function computation results */ -public class Memoizer { +public final class Memoizer { private final Map cache = new ConcurrentHashMap<>(); - private Memoizer() {} + private Memoizer() { + } + /** + * Put function computation results into Memoizer + * + * @param the type of the input to the function + * @param the type of the output of the function + * @param function represents a function that accepts one argument and produces a result + * @return Function + */ public static Function memoize(Function function) { return new Memoizer().internalMemoize(function); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java index 6e1bfbd30c1e..e01c5bba3221 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java @@ -8,7 +8,10 @@ import java.io.InputStream; import java.util.Properties; -public class PropertyLoader { +/** + * Load properties from files + */ +public final class PropertyLoader { private static final String PROJECT_PROPERTY_FILE = "/META-INF/project.properties"; @@ -21,14 +24,29 @@ public class PropertyLoader { private PropertyLoader() { } + /** + * Get project version from /META-INF/project.properties + * + * @return String project version + */ public static String getProjectVersion() { return getPropertyByName("project.version", PROJECT_PROPERTY_FILE); } + /** + * Get telemetry instrumentation key from /telemetry.config + * + * @return String telemetry instrumentation key + */ public static String getTelemetryInstrumentationKey() { return getPropertyByName("telemetry.instrumentationKey", TELEMETRY_CONFIG_FILE); } + /** + * Check if telemetry is allowed + * + * @return boolean if telemetry is allowed + */ public static boolean isApplicationTelemetryAllowed() { String allowed = getPropertyByName("cosmosdb.telemetryAllowed", APPLICATION_PROPERTY_FILE); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java index 48d041b8f531..56a980dcd3d0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java @@ -9,6 +9,9 @@ import java.time.Instant; import java.util.Map; +/** + * Data format class for telemetry event. + */ public class TelemetryEventData { private final String name; @@ -22,6 +25,12 @@ public class TelemetryEventData { private final String time; + /** + * Initialize data of a telemetry event + * + * @param eventName specify an event + * @param properties properties of event + */ public TelemetryEventData(String eventName, @NonNull Map properties) { Assert.hasText(eventName, "Event name should contain text."); @@ -33,22 +42,47 @@ public TelemetryEventData(String eventName, @NonNull Map propert time = Instant.now().toString(); } + /** + * Get name of event + * + * @return name value + */ public String getName() { return name; } + /** + * Get instrumentationKey of event + * + * @return instrumentationKey value + */ public String getInstrumentationKey() { return instrumentationKey; } + /** + * Get tags of event + * + * @return Tags value + */ public Tags getTags() { return tags; } + /** + * Get data of event + * + * @return EventData value + */ public EventData getData() { return data; } + /** + * Get time of event + * + * @return time value + */ public String getTime() { return time; } @@ -61,7 +95,7 @@ private static class Tags { @JsonProperty("ai.internal.sdkVersion") private final String aiInternalSdkVersion; - public Tags(String instance, String sdkVersion) { + Tags(String instance, String sdkVersion) { aiCloudRoleInstance = instance; aiInternalSdkVersion = sdkVersion; } @@ -81,7 +115,7 @@ private static class EventData { private final CustomData baseData = new CustomData(); - public EventData(String baseType) { + EventData(String baseType) { this.baseType = baseType; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java index 3ccf9731323c..d6ef8baac173 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java @@ -4,7 +4,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.http.*; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @@ -16,6 +20,9 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON; +/** + * Class for telemetry sender to send request and event data + */ public class TelemetrySender { private static final Logger LOGGER = LoggerFactory.getLogger(TelemetrySender.class); @@ -26,7 +33,8 @@ public class TelemetrySender { private static final String PROPERTY_SERVICE_NAME = "serviceName"; - private static final String PROJECT_INFO = "spring-data-cosmosdb/" + PropertyLoader.getProjectVersion(); + private static final String PROJECT_INFO = "spring-data-cosmosdb/" + + PropertyLoader.getProjectVersion(); private static final String TELEMETRY_TARGET_URL = "https://dc.services.visualstudio.com/v2/track"; @@ -57,16 +65,23 @@ private void sendTelemetryData(@NonNull TelemetryEventData eventData) { for (int i = 0; i < RETRY_LIMIT; i++) { response = executeRequest(eventData); - if (response != null && response.getStatusCode() == HttpStatus.OK) { + if (response != null + && response.getStatusCode() == HttpStatus.OK) { return; } } - if (response != null && response.getStatusCode() != HttpStatus.OK) { + if (response != null + && response.getStatusCode() != HttpStatus.OK) { LOGGER.warn("Failed to send telemetry data, response status code {}.", response.getStatusCode().toString()); } } + /** + * Send telemetry data according to event name + * + * @param name event name + */ public void send(String name) { Assert.hasText(name, "Event name should contain text."); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java new file mode 100644 index 000000000000..bbfa061b299a --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the classes of utils for cosmosdb + */ +package com.microsoft.azure.spring.data.cosmosdb.common; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java index 67be235cbc7a..005398857889 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java @@ -16,14 +16,27 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * To configure cosmos with client, cosmoscdb factory and template + */ @Configuration public abstract class AbstractCosmosConfiguration extends CosmosConfigurationSupport { + /** + * Declare CosmosClient bean. + * @param config of cosmosDbFactory + * @return CosmosClient bean + */ @Bean public CosmosClient cosmosClient(CosmosDBConfig config) { return this.cosmosDbFactory(config).getCosmosClient(); } + /** + * Declare CosmosSyncClient bean. + * @param config of cosmosDbFactory + * @return CosmosSyncClient bean + */ @Bean public CosmosSyncClient cosmosSyncClient(CosmosDBConfig config) { return this.cosmosDbFactory(config).getCosmosSyncClient(); @@ -33,23 +46,45 @@ public CosmosSyncClient cosmosSyncClient(CosmosDBConfig config) { @Autowired(required = false) private ObjectMapper objectMapper; + /** + * Declare CosmosDbFactory bean. + * @param config of cosmosDbFactory + * @return CosmosDbFactory bean + */ @Bean public CosmosDbFactory cosmosDbFactory(CosmosDBConfig config) { return new CosmosDbFactory(config); } + /** + * Declare CosmosTemplate bean. + * @param config of cosmosDbFactory + * @return CosmosTemplate bean + * @throws ClassNotFoundException if the class type is invalid + */ @Bean public CosmosTemplate cosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException { return new CosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(), config.getDatabase()); } + /** + * Declare ReactiveCosmosTemplate bean. + * @param config of cosmosDbFactory + * @return ReactiveCosmosTemplate bean + * @throws ClassNotFoundException if the class type is invalid + */ @Bean public ReactiveCosmosTemplate reactiveCosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException { return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(), config.getDatabase()); } + /** + * Declare MappingCosmosConverter bean. + * @return MappingCosmosConverter bean + * @throws ClassNotFoundException if the class type is invalid + */ @Bean public MappingCosmosConverter mappingCosmosConverter() throws ClassNotFoundException { return new MappingCosmosConverter(this.cosmosMappingContext(), objectMapper); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java index d30c04731d0b..458cc27cb253 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java @@ -20,13 +20,26 @@ import java.util.HashSet; import java.util.Set; +/** + * A support class for cosmos configuration to scan beans and get initial entities + */ public abstract class CosmosConfigurationSupport { + /** + * Declare ExpressionResolver bean. + * @param beanFactory used to initialize the embeddedValueResolver + * @return ExpressionResolver bean + */ @Bean public ExpressionResolver expressionResolver(BeanFactory beanFactory) { return new ExpressionResolver(beanFactory); } + /** + * Declare CosmosMappingContext bean. + * @return CosmosMappingContext bean + * @throws ClassNotFoundException if the class type is invalid + */ @Bean public CosmosMappingContext cosmosMappingContext() throws ClassNotFoundException { final CosmosMappingContext mappingContext = new CosmosMappingContext(); @@ -40,6 +53,11 @@ protected Collection getMappingBasePackages() { return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName()); } + /** + * Scan all base packages and get all beans + * @return initial entity set + * @throws ClassNotFoundException if the class type is invalid + */ protected Set> getInitialEntitySet() throws ClassNotFoundException { final Set> initialEntitySet = new HashSet<>(); @@ -50,6 +68,12 @@ protected Set> getInitialEntitySet() throws ClassNotFoundException { return initialEntitySet; } + /** + * Scan all beans under the given base package + * @param basePackage set the base location of beans + * @return initial entity set for found beans + * @throws ClassNotFoundException if the class type is invalid + */ protected Set> scanForEntities(String basePackage) throws ClassNotFoundException { if (!StringUtils.hasText(basePackage)) { return Collections.emptySet(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java index 6bd052c0f1bd..386e959119ab 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java @@ -12,6 +12,9 @@ import java.beans.ConstructorProperties; +/** + * Config properties of CosmosDB + */ public class CosmosDBConfig { private String uri; @@ -33,6 +36,19 @@ public class CosmosDBConfig { private boolean populateQueryMetrics; + /** + * Initialization + * @param uri must not be {@literal null} + * @param key must not be {@literal null} + * @param database must not be {@literal null} + * @param connectionPolicy must not be {@literal null} + * @param consistencyLevel must not be {@literal null} + * @param allowTelemetry must not be {@literal null} + * @param requestOptions must not be {@literal null} + * @param cosmosKeyCredential must not be {@literal null} + * @param responseDiagnosticsProcessor must not be {@literal null} + * @param populateQueryMetrics must not be {@literal null} + */ @ConstructorProperties({"uri", "key", "database", "connectionPolicy", "consistencyLevel", "allowTelemetry", "requestOptions", "cosmosKeyCredential", "responseDiagnosticsProcessor", "populateQueryMetrics"}) @@ -52,56 +68,111 @@ public CosmosDBConfig(String uri, String key, String database, ConnectionPolicy this.populateQueryMetrics = populateQueryMetrics; } + /** + * Gets uri + * @return uri + */ public String getUri() { return uri; } + /** + * Gets key + * @return key + */ public String getKey() { return key; } + /** + * Gets database + * @return database + */ public String getDatabase() { return database; } + /** + * Gets connection policy + * @return connectionPolicy + */ public ConnectionPolicy getConnectionPolicy() { return connectionPolicy; } + /** + * Gets consistency level + * @return ConsistencyLevel + */ public ConsistencyLevel getConsistencyLevel() { return consistencyLevel; } + /** + * Checks if telemetry is allowed + * @return boolean + */ public boolean isAllowTelemetry() { return allowTelemetry; } + /** + * Gets request options + * @return RequestOptions + */ public RequestOptions getRequestOptions() { return requestOptions; } + /** + * Gets Cosmos key credential + * @return CosmosKeyCredential + */ public CosmosKeyCredential getCosmosKeyCredential() { return cosmosKeyCredential; } + /** + * Gets response diagnostics processor + * @return ResponseDiagnosticsProcessor + */ public ResponseDiagnosticsProcessor getResponseDiagnosticsProcessor() { return responseDiagnosticsProcessor; } + /** + * Checks if is populate query metrics + * @return boolean + */ public boolean isPopulateQueryMetrics() { return populateQueryMetrics; } + /** + * Sets response diagnostics processor + * @param responseDiagnosticsProcessor must not be {@literal null} + */ public void setResponseDiagnosticsProcessor(ResponseDiagnosticsProcessor responseDiagnosticsProcessor) { this.responseDiagnosticsProcessor = responseDiagnosticsProcessor; } + /** + * Sets populate query metrics + * @param populateQueryMetrics must not be {@literal null} + */ public void setPopulateQueryMetrics(boolean populateQueryMetrics) { this.populateQueryMetrics = populateQueryMetrics; } - public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential, - String database) { + /** + * create a CosmosDBConfigBuilder with cosmos uri, cosmosKeyCredential and database name + * @param uri must not be {@literal null} + * @param cosmosKeyCredential must not be {@literal null} + * @param database must not be {@literal null} + * @return CosmosDBConfigBuilder + */ + public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, CosmosKeyCredential cosmosKeyCredential, + String database) { return defaultBuilder() .uri(uri) .cosmosKeyCredential(cosmosKeyCredential) @@ -111,7 +182,14 @@ public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosm .requestOptions(new RequestOptions()); } - public static CosmosDBConfigBuilder builder(String uri, String key, String database) { + /** + * create a CosmosDBConfigBuilder with cosmos uri, key and database name + * @param uri must not be {@literal null} + * @param key must not be {@literal null} + * @param database must not be {@literal null} + * @return CosmosDBConfigBuilder + */ + public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, String key, String database) { return defaultBuilder() .uri(uri) .key(key) @@ -121,21 +199,35 @@ public static CosmosDBConfigBuilder builder(String uri, String key, String datab .requestOptions(new RequestOptions()); } - public static CosmosDBConfigBuilder builder(String connectionString, String database) { + /** + * create a CosmosDBConfigBuilder with connection string and database name + * @param connectionString must not be {@literal null} + * @param database must not be {@literal null} + * @return CosmosDBConfigBuilder + * @throws CosmosDBAccessException for invalid connection string + */ + public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String connectionString, String database) { Assert.hasText(connectionString, "connection string should have text!"); try { final String uri = connectionString.split(";")[0].split("=")[1]; final String key = connectionString.split(";")[1].split("=")[1]; - return builder(uri, key, database); + return cosmosDBConfigbuilder(uri, key, database); } catch (ArrayIndexOutOfBoundsException e) { throw new CosmosDBAccessException("could not parse connection string"); } } + /** + * create a CosmosDBConfigBuilder instance + * @return CosmosDBConfigBuilder + */ public static CosmosDBConfigBuilder defaultBuilder() { return new CosmosDBConfigBuilder(); } + /** + * Builder class for cosmos db config + */ public static class CosmosDBConfigBuilder { private String uri; private String key; @@ -151,63 +243,133 @@ public static class CosmosDBConfigBuilder { CosmosDBConfigBuilder() { } + /** + * Set uri + * + * @param uri value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder uri(String uri) { this.uri = uri; return this; } + /** + * Set key + * + * @param key value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder key(String key) { this.key = key; return this; } + /** + * Set database + * + * @param database value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder database(String database) { this.database = database; return this; } + /** + * Set connectionPolicy + * + * @param connectionPolicy value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder connectionPolicy(ConnectionPolicy connectionPolicy) { this.connectionPolicy = connectionPolicy; return this; } + /** + * Set consistencyLevel + * + * @param consistencyLevel value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder consistencyLevel(ConsistencyLevel consistencyLevel) { this.consistencyLevel = consistencyLevel; return this; } + /** + * Set allowTelemetry + * + * @param allowTelemetry value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder allowTelemetry(boolean allowTelemetry) { this.allowTelemetry = allowTelemetry; return this; } + /** + * Set requestOptions + * + * @param requestOptions value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder requestOptions(RequestOptions requestOptions) { this.requestOptions = requestOptions; return this; } + /** + * Set cosmosKeyCredential + * + * @param cosmosKeyCredential value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder cosmosKeyCredential(CosmosKeyCredential cosmosKeyCredential) { this.cosmosKeyCredential = cosmosKeyCredential; return this; } + /** + * Set responseDiagnosticsProcessor + * + * @param responseDiagnosticsProcessor value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder responseDiagnosticsProcessor(ResponseDiagnosticsProcessor responseDiagnosticsProcessor) { this.responseDiagnosticsProcessor = responseDiagnosticsProcessor; return this; } + /** + * Set populateQueryMetrics + * + * @param populateQueryMetrics value to initialize + * @return CosmosDBConfigBuilder + */ public CosmosDBConfigBuilder populateQueryMetrics(boolean populateQueryMetrics) { this.populateQueryMetrics = populateQueryMetrics; return this; } + /** + * Build a CosmosDBConfig instance + * + * @return CosmosDBConfig + */ public CosmosDBConfig build() { return new CosmosDBConfig(this.uri, this.key, this.database, this.connectionPolicy, this.consistencyLevel, this.allowTelemetry, this.requestOptions, this.cosmosKeyCredential, this.responseDiagnosticsProcessor, this.populateQueryMetrics); } + /** + * Generate string info of instance + * + * @return String + */ public String toString() { return "CosmosDBConfig.CosmosDBConfigBuilder(uri=" + this.uri diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java new file mode 100644 index 000000000000..f2fcbfbf6754 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the classes to configure properties of cosmos db + */ +package com.microsoft.azure.spring.data.cosmosdb.config; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java index 907ad765b9ff..458e29377112 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java @@ -13,78 +13,269 @@ import java.util.List; +/** + * Interface for cosmosdb operations + */ public interface CosmosOperations { /** * Use getContainerName() instead * @param domainType class type * @return container name + * @deprecated Use {@link #getContainerName(Class)} instead */ @Deprecated String getCollectionName(Class domainType); + /** + * To get container name by domaintype + * @param domainType class type + * @return String + */ String getContainerName(Class domainType); /** * Use createContainerIfNotExists() instead * @param information cosmos entity information * @return created container properties + * @deprecated Use {@link #createContainerIfNotExists(CosmosEntityInformation)} instead */ @Deprecated CosmosContainerProperties createCollectionIfNotExists(CosmosEntityInformation information); + /** + * Creates container if not exists + * @param information CosmosEntityInformation + * @return CosmosContainerProperties + */ CosmosContainerProperties createContainerIfNotExists(CosmosEntityInformation information); + /** + * Find the DocumentQuery, find all the items specified by domain type. + * + * @param domainType the domain type + * @param class type of domain + * @return found results in a List + */ List findAll(Class domainType); + /** + * Find the DocumentQuery, find all the items specified by domain type in the given container. + * + * @param containerName the container name + * @param domainType the domain type + * @param class type of domain + * @return found results in a List + */ List findAll(String containerName, Class domainType); + /** + * Find the DocumentQuery, find all the items specified by domain type in the given container. + * + * @param partitionKey the partition key + * @param domainType the domain type + * @param class type of domain + * @return found results in a List + */ List findAll(PartitionKey partitionKey, Class domainType); + /** + * Finds item by id + * @param id must not be {@literal null} + * @param domainType must not be {@literal null} + * @param type class of domain type + * @return found item + */ T findById(Object id, Class domainType); + /** + * Finds item by id + * @param containerName must not be {@literal null} + * @param id must not be {@literal null} + * @param domainType must not be {@literal null} + * @param type class of domain type + * @return found item + */ T findById(String containerName, Object id, Class domainType); + /** + * Finds item by id + * @param id must not be {@literal null} + * @param domainType must not be {@literal null} + * @param partitionKey must not be {@literal null} + * @param type class of domain type + * @return found item + */ T findById(Object id, Class domainType, PartitionKey partitionKey); + /** + * Inserts item + * + * @param objectToSave must not be {@literal null} + * @param partitionKey must not be {@literal null} + * @param type class of domain type + * @return the inserted item + */ T insert(T objectToSave, PartitionKey partitionKey); + /** + * Inserts item + * + * @param containerName must not be {@literal null} + * @param objectToSave must not be {@literal null} + * @param partitionKey must not be {@literal null} + * @param type class of domain type + * @return the inserted item + */ T insert(String containerName, T objectToSave, PartitionKey partitionKey); + /** + * Upserts an item with partition key + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + */ void upsert(T object, PartitionKey partitionKey); + /** + * Upserts an item into container with partition key + * @param containerName the container name + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + */ void upsert(String containerName, T object, PartitionKey partitionKey); + /** + * Upserts an item and return item properties + * @param containerName the container name + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + * @return upsert object entity + */ T upsertAndReturnEntity(String containerName, T object, PartitionKey partitionKey); + /** + * Delete an item by id + * + * @param containerName the container name + * @param id the id + * @param partitionKey the partition key + */ void deleteById(String containerName, Object id, PartitionKey partitionKey); + /** + * Delete all items in a container + * + * @param containerName the container name + * @param domainType the partition key path + */ void deleteAll(String containerName, Class domainType); /** * Use deleteContainer() instead * @param containerName container name + * @deprecated Use {@link #deleteContainer(String)} instead. */ @Deprecated void deleteCollection(String containerName); + /** + * Delete container + * + * @param containerName the container name + */ void deleteContainer(String containerName); + /** + * Delete items matching query + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type class of domaintype + * @return deleted items in a List + */ List delete(DocumentQuery query, Class domainType, String containerName); + /** + * Find query + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type class of domaintype + * @return found results in a List + */ List find(DocumentQuery query, Class domainType, String containerName); + /** + * Find by ids + * + * @param ids iterable of ids + * @param domainType type class + * @param containerName the container name + * @param type of domainType + * @param type of ID + * @return Mono + */ List findByIds(Iterable ids, Class domainType, String containerName); + /** + * Exists + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type of domainType + * @return Boolean + */ Boolean exists(DocumentQuery query, Class domainType, String containerName); + /** + * Find all items in a given container with partition key + * + * @param pageable Pageable object + * @param domainType the domainType + * @param containerName the container name + * @param type of domainType + * @return Page + */ Page findAll(Pageable pageable, Class domainType, String containerName); + /** + * Pagination query + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type class of domaintype + * @return Page + */ Page paginationQuery(DocumentQuery query, Class domainType, String containerName); + /** + * Count + * + * @param containerName the container name + * @return count result + */ long count(String containerName); + /** + * Count + * + * @param query the document query + * @param domainType the domain type + * @param containerName the container name + * @param type class of domaintype + * @return count result + */ long count(DocumentQuery query, Class domainType, String containerName); + /** + * To get converter + * @return MappingCosmosConverter + */ MappingCosmosConverter getConverter(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java index 8f539004e1e7..bc45fd3af611 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java @@ -3,30 +3,31 @@ package com.microsoft.azure.spring.data.cosmosdb.core; +import com.azure.data.cosmos.CosmosItemResponse; import com.azure.data.cosmos.AccessCondition; import com.azure.data.cosmos.AccessConditionType; -import com.azure.data.cosmos.CosmosClient; -import com.azure.data.cosmos.CosmosContainerProperties; -import com.azure.data.cosmos.CosmosContainerResponse; import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.SqlQuerySpec; import com.azure.data.cosmos.CosmosItemRequestOptions; -import com.azure.data.cosmos.CosmosItemResponse; -import com.azure.data.cosmos.FeedOptions; import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.CosmosContainerResponse; import com.azure.data.cosmos.PartitionKey; -import com.azure.data.cosmos.SqlQuerySpec; import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; -import com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils; import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer; import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator; import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator; -import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageImpl; -import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageImpl; import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType; import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest; import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -37,8 +38,7 @@ import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -50,6 +50,9 @@ import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.exceptionHandler; import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.findAPIExceptionHandler; +/** + * Template class for cosmos db + */ public class CosmosTemplate implements CosmosOperations, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(CosmosTemplate.class); @@ -65,6 +68,12 @@ public class CosmosTemplate implements CosmosOperations, ApplicationContextAware private Function, CosmosEntityInformation> entityInfoCreator = Memoizer.memoize(this::getCosmosEntityInformation); + /** + * Initialization + * @param cosmosDbFactory must not be {@literal null} + * @param mappingCosmosConverter must not be {@literal null} + * @param dbName must not be {@literal null} + */ public CosmosTemplate(CosmosDbFactory cosmosDbFactory, MappingCosmosConverter mappingCosmosConverter, String dbName) { @@ -79,15 +88,36 @@ public CosmosTemplate(CosmosDbFactory cosmosDbFactory, this.isPopulateQueryMetrics = cosmosDbFactory.getConfig().isPopulateQueryMetrics(); } + /** + * Sets the application context + * @param applicationContext must not be {@literal null} + * @throws BeansException the bean exception + */ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { } + /** + * + * Inserts item + * @param objectToSave must not be {@literal null} + * @param partitionKey must not be {@literal null} + * @param type class of domain type + * @return the inserted item + */ public T insert(T objectToSave, PartitionKey partitionKey) { Assert.notNull(objectToSave, "domainType should not be null"); return insert(getContainerName(objectToSave.getClass()), objectToSave, partitionKey); } + /** + * Inserts item into the given container + * @param containerName must not be {@literal null} + * @param objectToSave must not be {@literal null} + * @param partitionKey must not be {@literal null} + * @param type class of domain type + * @return the inserted item + */ public T insert(String containerName, T objectToSave, PartitionKey partitionKey) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); Assert.notNull(objectToSave, "objectToSave should not be null"); @@ -116,6 +146,13 @@ public T insert(String containerName, T objectToSave, PartitionKey partition return mappingCosmosConverter.read(domainType, response.properties()); } + /** + * Finds item by id + * @param id must not be {@literal null} + * @param domainType must not be {@literal null} + * @param type class of domain type + * @return found item + */ public T findById(Object id, Class domainType) { Assert.notNull(domainType, "domainType should not be null"); @@ -145,6 +182,14 @@ public T findById(Object id, Class domainType, PartitionKey partitionKey) .block(); } + /** + * Finds item by id + * @param containerName must not be {@literal null} + * @param id must not be {@literal null} + * @param domainType must not be {@literal null} + * @param type class of domain type + * @return found item + */ public T findById(String containerName, Object id, Class domainType) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); Assert.notNull(domainType, "domainType should not be null"); @@ -172,16 +217,37 @@ public T findById(String containerName, Object id, Class domainType) { .blockFirst(); } + /** + * Upserts an item with partition key + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + */ public void upsert(T object, PartitionKey partitionKey) { Assert.notNull(object, "Upsert object should not be null"); upsert(getContainerName(object.getClass()), object, partitionKey); } + /** + * Upserts an item into container with partition key + * @param containerName the container name + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + */ public void upsert(String containerName, T object, PartitionKey partitionKey) { upsertAndReturnEntity(containerName, object, partitionKey); } + /** + * Upserts an item and return item properties + * @param containerName the container name + * @param object upsert object + * @param partitionKey the partition key + * @param type of upsert object + * @return upsert object entity + */ public T upsertAndReturnEntity(String containerName, T object, PartitionKey partitionKey) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); Assert.notNull(object, "Upsert object should not be null"); @@ -210,12 +276,27 @@ public T upsertAndReturnEntity(String containerName, T object, PartitionKey return mappingCosmosConverter.read(domainType, cosmosItemResponse.properties()); } + /** + * Find the DocumentQuery, find all the items specified by domain type. + * + * @param domainType the domain type + * @param class type of domain + * @return found results in a List + */ public List findAll(Class domainType) { Assert.notNull(domainType, "domainType should not be null"); return findAll(getContainerName(domainType), domainType); } + /** + * Find the DocumentQuery, find all the items specified by domain type in the given container. + * + * @param containerName the container name + * @param domainType the domain type + * @param class type of domain + * @return found results in a List + */ public List findAll(String containerName, final Class domainType) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); Assert.notNull(domainType, "domainType should not be null"); @@ -255,6 +336,12 @@ public List findAll(PartitionKey partitionKey, final Class domainType) .block(); } + /** + * Delete the DocumentQuery, delete all the items in the given container. + * + * @param containerName Container name of database + * @param domainType the domain type + */ public void deleteAll(@NonNull String containerName, @NonNull Class domainType) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); @@ -281,6 +368,11 @@ public void deleteContainer(@NonNull String containerName) { .block(); } + /** + * To get collection name by domaintype + * @param domainType class type + * @return String + */ public String getCollectionName(Class domainType) { return getContainerName(domainType); } @@ -307,8 +399,8 @@ public CosmosContainerProperties createContainerIfNotExists(CosmosEntityInformat fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, cosmosDatabaseResponse, null); final CosmosContainerProperties cosmosContainerProperties = new CosmosContainerProperties( - information.getContainerName(), - "/" + information.getPartitionKeyFieldName()); + information.getContainerName(), "/" + + information.getPartitionKeyFieldName()); cosmosContainerProperties.defaultTimeToLive(information.getTimeToLive()); cosmosContainerProperties.indexingPolicy(information.getIndexingPolicy()); return cosmosDatabaseResponse @@ -325,6 +417,14 @@ public CosmosContainerProperties createContainerIfNotExists(CosmosEntityInformat return response.properties(); } + /** + * Delete the DocumentQuery, need to query by id at first, then delete the item + * from the result. + * + * @param containerName Container name of database + * @param id item id + * @param partitionKey the paritition key + */ public void deleteById(String containerName, Object id, PartitionKey partitionKey) { Assert.hasText(containerName, "containerName should not be null, empty or only whitespaces"); assertValidId(id); @@ -358,6 +458,14 @@ public List findByIds(Iterable ids, Class domainType, String c return find(query, domainType, containerName); } + /** + * Finds the document query items + * @param query The representation for query method. + * @param domainType Class of domain + * @param containerName Container name of database + * @param class of domainType + * @return All the found items as List. + */ public List find(@NonNull DocumentQuery query, @NonNull Class domainType, String containerName) { Assert.notNull(query, "DocumentQuery should not be null."); Assert.notNull(domainType, "domainType should not be null."); @@ -369,6 +477,14 @@ public List find(@NonNull DocumentQuery query, @NonNull Class domainTy .collect(Collectors.toList()); } + /** + * Checks if document query items exist + * @param query The representation for query method. + * @param domainType Class of domain + * @param containerName Container name of database + * @param class of domainType + * @return if items exist + */ public Boolean exists(@NonNull DocumentQuery query, @NonNull Class domainType, String containerName) { return this.find(query, domainType, containerName).size() > 0; } @@ -378,10 +494,10 @@ public Boolean exists(@NonNull DocumentQuery query, @NonNull Class domain * from the result. * The cosmosdb Sql API do _NOT_ support DELETE query, we cannot add one DeleteQueryGenerator. * - * @param query The representation for query method. - * @param domainType Class of domain + * @param query The representation for query method. + * @param domainType Class of domain * @param containerName Container name of database - * @param class of domainType + * @param class of domainType * @return All the deleted items as List. */ @Override @@ -442,7 +558,8 @@ public Page paginationQuery(DocumentQuery query, Class domainType, Str final Iterator it = feedResponse.results().iterator(); final List result = new ArrayList<>(); - for (int index = 0; it.hasNext() && index < pageable.getPageSize(); index++) { + for (int index = 0; it.hasNext() + && index < pageable.getPageSize(); index++) { final CosmosItemProperties cosmosItemProperties = it.next(); if (cosmosItemProperties == null) { @@ -458,7 +575,8 @@ public Page paginationQuery(DocumentQuery query, Class domainType, Str int pageSize; - if (contentSize < pageable.getPageSize() && contentSize > 0) { + if (contentSize < pageable.getPageSize() + && contentSize > 0) { // If the content size is less than page size, // this means, cosmosDB is returning less items than page size, // because of either RU limit, or payload limit @@ -581,7 +699,8 @@ private CosmosItemResponse deleteItem(@NonNull CosmosItemProperties cosmosItemPr PartitionKey partitionKey = null; - if (!partitionKeyNames.isEmpty() && StringUtils.hasText(partitionKeyNames.get(0))) { + if (!partitionKeyNames.isEmpty() + && StringUtils.hasText(partitionKeyNames.get(0))) { partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0))); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java index e54d3d4513b2..64bf11e91877 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java @@ -11,57 +11,226 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +/** + * Operation class of reactive cosmos + */ public interface ReactiveCosmosOperations { + /** + * Get container name + * + * @param domainType the domainType + * @return container name + */ String getContainerName(Class domainType); /** * Use createContainerIfNotExists() instead * @param information cosmos entity information * @return Mono of cosmos container response + * @deprecated use createContainerIfNotExists(CosmosEntityInformation) instead. */ @Deprecated - Mono createCollectionIfNotExists(CosmosEntityInformation information); + Mono createCollectionIfNotExists(CosmosEntityInformation information); - Mono createContainerIfNotExists(CosmosEntityInformation information); + /** + * Creates a container if it doesn't already exist + * + * @param information the CosmosEntityInformation + * @return Mono + */ + Mono createContainerIfNotExists(CosmosEntityInformation information); + /** + * Find all items in a given container + * + * @param containerName the containerName + * @param domainType the domainType + * @param type of domainType + * @return Flux + */ Flux findAll(String containerName, Class domainType); + /** + * Find all items in a given container + * + * @param domainType the domainType + * @param type of domainType + * @return Flux + */ Flux findAll(Class domainType); + /** + * Find all items in a given container with partition key + * + * @param partitionKey partition Key + * @param domainType the domainType + * @param type of domainType + * @return Flux + */ Flux findAll(PartitionKey partitionKey, Class domainType); + /** + * Find by id + * + * @param id the id + * @param domainType the domainType + * @param type of domainType + * @return Mono + */ Mono findById(Object id, Class domainType); + /** + * Find by id + * + * @param containerName the containername + * @param id the id + * @param domainType type class + * @param type of domainType + * @return Mono + */ Mono findById(String containerName, Object id, Class domainType); + /** + * Find by id + * + * @param id the id + * @param domainType type class + * @param partitionKey partition Key + * @param type of domainType + * @return Mono + */ Mono findById(Object id, Class domainType, PartitionKey partitionKey); + /** + * Insert + * + * @param objectToSave the object to save + * @param partitionKey the partition key + * @param type of inserted objectToSave + * @return Mono + */ Mono insert(T objectToSave, PartitionKey partitionKey); + /** + * Insert + * + * @param type of inserted objectToSave + * @param containerName the container name + * @param objectToSave the object to save + * @param partitionKey the partition key + * @return Mono + */ Mono insert(String containerName, Object objectToSave, PartitionKey partitionKey); + /** + * Upsert + * + * @param object the object to upsert + * @param partitionKey the partition key + * @param type class of object + * @return Mono + */ Mono upsert(T object, PartitionKey partitionKey); + /** + * Upsert + * + * @param containerName the container name + * @param object the object to save + * @param partitionKey the partition key + * @param type class of object + * @return Mono + */ Mono upsert(String containerName, T object, PartitionKey partitionKey); + /** + * Delete an item by id + * + * @param containerName the container name + * @param id the id + * @param partitionKey the partition key + * @return void Mono + */ Mono deleteById(String containerName, Object id, PartitionKey partitionKey); + /** + * Delete all items in a container + * + * @param containerName the container name + * @param partitionKey the partition key path + * @return void Mono + */ Mono deleteAll(String containerName, String partitionKey); + /** + * Delete container + * + * @param containerName the container name + */ void deleteContainer(String containerName); + /** + * Delete items matching query + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type class of domaintype + * @return Flux + */ Flux delete(DocumentQuery query, Class domainType, String containerName); + /** + * Find items + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @param type class of domaintype + * @return Flux + */ Flux find(DocumentQuery query, Class domainType, String containerName); + /** + * Exists + * + * @param query the document query + * @param domainType type class + * @param containerName the container name + * @return Mono + */ Mono exists(DocumentQuery query, Class domainType, String containerName); + /** + * Exists + * @param id the id + * @param domainType type class + * @param containerName the containercontainer nam,e + * @return Mono + */ Mono existsById(Object id, Class domainType, String containerName); + /** + * Count + * + * @param containerName the container name + * @return Mono + */ Mono count(String containerName); + /** + * Count + * + * @param query the document query + * @param containerName the container name + * @return Mono + */ Mono count(DocumentQuery query, String containerName); + /** + * To get converter + * @return MappingCosmosConverter + */ MappingCosmosConverter getConverter(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java index e5639ec799b0..07a6e861c397 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java @@ -5,17 +5,16 @@ import com.azure.data.cosmos.AccessCondition; import com.azure.data.cosmos.AccessConditionType; -import com.azure.data.cosmos.CosmosClient; -import com.azure.data.cosmos.CosmosContainerProperties; -import com.azure.data.cosmos.CosmosContainerResponse; import com.azure.data.cosmos.CosmosItemProperties; +import com.azure.data.cosmos.SqlQuerySpec; import com.azure.data.cosmos.CosmosItemRequestOptions; -import com.azure.data.cosmos.FeedOptions; import com.azure.data.cosmos.FeedResponse; +import com.azure.data.cosmos.FeedOptions; +import com.azure.data.cosmos.CosmosClient; +import com.azure.data.cosmos.CosmosContainerProperties; +import com.azure.data.cosmos.CosmosContainerResponse; import com.azure.data.cosmos.PartitionKey; -import com.azure.data.cosmos.SqlQuerySpec; import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory; -import com.microsoft.azure.spring.data.cosmosdb.common.CosmosdbUtils; import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer; import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter; import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator; @@ -42,6 +41,9 @@ import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.exceptionHandler; import static com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBExceptionUtils.findAPIExceptionHandler; +/** + * Template class of reactive cosmos + */ @SuppressWarnings("unchecked") public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, ApplicationContextAware { private static final String COUNT_VALUE_KEY = "_aggregate"; @@ -61,9 +63,9 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica /** * Constructor * - * @param cosmosDbFactory the cosmosdbfactory + * @param cosmosDbFactory the cosmosdbfactory * @param mappingCosmosConverter the mappingCosmosConverter - * @param dbName database name + * @param dbName database name */ public ReactiveCosmosTemplate(CosmosDbFactory cosmosDbFactory, MappingCosmosConverter mappingCosmosConverter, @@ -95,7 +97,7 @@ public void setApplicationContext(@NonNull ApplicationContext applicationContext * @return Mono containing CosmosContainerResponse */ @Override - public Mono createCollectionIfNotExists(CosmosEntityInformation information) { + public Mono createCollectionIfNotExists(CosmosEntityInformation information) { return createContainerIfNotExists(information); } @@ -106,7 +108,7 @@ public Mono createCollectionIfNotExists(CosmosEntityInf * @return Mono containing CosmosContainerResponse */ @Override - public Mono createContainerIfNotExists(CosmosEntityInformation information) { + public Mono createContainerIfNotExists(CosmosEntityInformation information) { return cosmosClient .createDatabaseIfNotExists(this.databaseName) @@ -139,7 +141,7 @@ public Mono createContainerIfNotExists(CosmosEntityInfo * Find all items in a given container * * @param containerName the containerName - * @param domainType the domainType + * @param domainType the domainType * @return Flux with all the found items or error */ @Override @@ -188,7 +190,7 @@ public Flux findAll(PartitionKey partitionKey, Class domainType) { /** * Find by id * - * @param id the id + * @param id the id * @param domainType the domainType * @return Mono with the item or error */ @@ -202,8 +204,8 @@ public Mono findById(Object id, Class domainType) { * Find by id * * @param containerName the containername - * @param id the id - * @param domainType the entity class + * @param id the id + * @param domainType the entity class * @return Mono with the item or error */ @Override @@ -221,13 +223,13 @@ public Mono findById(String containerName, Object id, Class domainType .getContainer(containerName) .queryItems(query, options) .flatMap(cosmosItemFeedResponse -> { - fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, - null, cosmosItemFeedResponse); - return Mono.justOrEmpty(cosmosItemFeedResponse - .results() - .stream() - .map(cosmosItem -> toDomainObject(domainType, cosmosItem)) - .findFirst()); + fillAndProcessResponseDiagnostics(responseDiagnosticsProcessor, + null, cosmosItemFeedResponse); + return Mono.justOrEmpty(cosmosItemFeedResponse + .results() + .stream() + .map(cosmosItem -> toDomainObject(domainType, cosmosItem)) + .findFirst()); }) .onErrorResume(throwable -> findAPIExceptionHandler("Failed to find item", throwable)) @@ -237,9 +239,9 @@ public Mono findById(String containerName, Object id, Class domainType /** * Find by id * - * @param id the id - * @param domainType the entity class - * @param partitionKey partition Key + * @param id the id + * @param domainType the entity class + * @param partitionKey partition Key * @return Mono with the item or error */ @Override @@ -265,6 +267,7 @@ public Mono findById(Object id, Class domainType, PartitionKey partiti /** * Insert * + * @param type of inserted objectToSave * @param objectToSave the object to save * @param partitionKey the partition key * @return Mono with the item or error @@ -302,9 +305,10 @@ public Mono insert(T objectToSave) { /** * Insert * + * @param type of inserted objectToSave * @param containerName the container name - * @param objectToSave the object to save - * @param partitionKey the partition key + * @param objectToSave the object to save + * @param partitionKey the partition key * @return Mono with the item or error */ public Mono insert(String containerName, Object objectToSave, PartitionKey partitionKey) { @@ -332,7 +336,7 @@ public Mono insert(String containerName, Object objectToSave, PartitionKe /** * Upsert * - * @param object the object to upsert + * @param object the object to upsert * @param partitionKey the partition key * @return Mono with the item or error */ @@ -345,8 +349,8 @@ public Mono upsert(T object, PartitionKey partitionKey) { * Upsert * * @param containerName the container name - * @param object the object to save - * @param partitionKey the partition key + * @param object the object to save + * @param partitionKey the partition key * @return Mono with the item or error */ @Override @@ -376,8 +380,8 @@ public Mono upsert(String containerName, T object, PartitionKey partition * Delete an item by id * * @param containerName the container name - * @param id the id - * @param partitionKey the partition key + * @param id the id + * @param partitionKey the partition key * @return void Mono */ @Override @@ -406,7 +410,7 @@ public Mono deleteById(String containerName, Object id, PartitionKey parti /** * Delete all items in a container * - * @param containerName the container name + * @param containerName the container name * @param partitionKeyName the partition key path * @return void Mono */ @@ -448,8 +452,8 @@ public Mono deleteAll(String containerName, String partitionKeyName) { /** * Delete items matching query * - * @param query the document query - * @param domainType the entity class + * @param query the document query + * @param domainType the entity class * @param containerName the container name * @return Mono */ @@ -469,8 +473,8 @@ public Flux delete(DocumentQuery query, Class domainType, String conta /** * Find items * - * @param query the document query - * @param domainType the entity class + * @param query the document query + * @param domainType the entity class * @param containerName the container name * @return Flux with found items or error */ @@ -483,8 +487,8 @@ public Flux find(DocumentQuery query, Class domainType, String contain /** * Exists * - * @param query the document query - * @param domainType the entity class + * @param query the document query + * @param domainType the entity class * @param containerName the container name * @return Mono with a boolean or error */ @@ -520,7 +524,7 @@ public Mono count(String containerName) { /** * Count * - * @param query the document query + * @param query the document query * @param containerName the container name * @return Mono with count or error */ @@ -534,6 +538,14 @@ public MappingCosmosConverter getConverter() { return mappingCosmosConverter; } + /** + *Count + * + * @param query the document query + * @param isCrossPartitionQuery flag of cross partition + * @param containerName the container name + * @return Mono + */ public Mono count(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) { return getCountValue(query, isCrossPartitionQuery, containerName); } @@ -640,7 +652,8 @@ private Mono deleteItem(@NonNull CosmosItemProperties cosm PartitionKey partitionKey = null; - if (!partitionKeyNames.isEmpty() && StringUtils.hasText(partitionKeyNames.get(0))) { + if (!partitionKeyNames.isEmpty() + && StringUtils.hasText(partitionKeyNames.get(0))) { partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0))); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java index 6745e055809a..316eee94c4f1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java @@ -8,18 +8,34 @@ import com.azure.data.cosmos.FeedResponseDiagnostics; import com.azure.data.cosmos.Resource; +/** + * Diagnostics class of cosmos and feed response + */ public class ResponseDiagnostics { private CosmosResponseDiagnostics cosmosResponseDiagnostics; private FeedResponseDiagnostics feedResponseDiagnostics; private CosmosResponseStatistics cosmosResponseStatistics; + /** + * Initialization + * + * @param cosmosResponseDiagnostics cannot be null + * @param feedResponseDiagnostics cannot be null + */ public ResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics, FeedResponseDiagnostics feedResponseDiagnostics) { this.cosmosResponseDiagnostics = cosmosResponseDiagnostics; this.feedResponseDiagnostics = feedResponseDiagnostics; } + /** + * Initialization + * + * @param cosmosResponseDiagnostics cannot be null + * @param feedResponseDiagnostics cannot be null + * @param cosmosResponseStatistics cannot be null + */ public ResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics, FeedResponseDiagnostics feedResponseDiagnostics, CosmosResponseStatistics cosmosResponseStatistics) { @@ -28,26 +44,50 @@ public ResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics, this.cosmosResponseStatistics = cosmosResponseStatistics; } + /** + * To get diagnostics of cosmos response + * @return CosmosResponseDiagnostics + */ public CosmosResponseDiagnostics getCosmosResponseDiagnostics() { return cosmosResponseDiagnostics; } + /** + * To set diagnostics of cosmos response + * @param cosmosResponseDiagnostics cannot be null + */ public void setCosmosResponseDiagnostics(CosmosResponseDiagnostics cosmosResponseDiagnostics) { this.cosmosResponseDiagnostics = cosmosResponseDiagnostics; } + /** + * To get diagnostics of feed response + * @return FeedResponseDiagnostics + */ public FeedResponseDiagnostics getFeedResponseDiagnostics() { return feedResponseDiagnostics; } + /** + * To set diagnostics of feed response + * @param feedResponseDiagnostics cannot be null + */ public void setFeedResponseDiagnostics(FeedResponseDiagnostics feedResponseDiagnostics) { this.feedResponseDiagnostics = feedResponseDiagnostics; } + /** + * To get the statistics value of cosmos response + * @return CosmosResponseStatistics + */ public CosmosResponseStatistics getCosmosResponseStatistics() { return cosmosResponseStatistics; } + /** + * To set statistics of cosmos response + * @param cosmosResponseStatistics cannot be null + */ public void setCosmosResponseStatistics(CosmosResponseStatistics cosmosResponseStatistics) { this.cosmosResponseStatistics = cosmosResponseStatistics; } @@ -79,30 +119,50 @@ public String toString() { return diagnostics.toString(); } + /** + * Generates statistics from cosmos response + */ public static class CosmosResponseStatistics { private final double requestCharge; private final String activityId; + /** + * Initialization + * + * @param feedResponse response from feed + * @param type of cosmosResponse + */ public CosmosResponseStatistics(FeedResponse feedResponse) { this.requestCharge = feedResponse.requestCharge(); this.activityId = feedResponse.activityId(); } + /** + * To get the charge value of request + * @return double + */ public double getRequestCharge() { return requestCharge; } + /** + * To get the activity id + * @return String + */ public String getActivityId() { return activityId; } @Override public String toString() { - return "CosmosResponseStatistics{" + - "requestCharge=" + requestCharge + - ", activityId='" + activityId + '\'' + - '}'; + return "CosmosResponseStatistics{" + + "requestCharge=" + + requestCharge + + ", activityId='" + + activityId + + '\'' + + '}'; } } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java index 3e1542c6b328..b8407cc36c03 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java @@ -5,6 +5,9 @@ import javax.annotation.Nullable; +/** + * Interface for processing cosmosdb response + */ public interface ResponseDiagnosticsProcessor { /** diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java index 6ce4fba3c2e7..bb409059c338 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java @@ -29,6 +29,9 @@ import static com.microsoft.azure.spring.data.cosmosdb.Constants.ISO_8601_COMPATIBLE_DATE_PATTERN; +/** + * A converter class between common types and cosmosItemProperties + */ @SuppressWarnings("unchecked") public class MappingCosmosConverter implements EntityConverter, CosmosPersistentProperty, @@ -41,13 +44,18 @@ public class MappingCosmosConverter private ApplicationContext applicationContext; private ObjectMapper objectMapper; + /** + * Initialization + * @param mappingContext must not be {@literal null} + * @param objectMapper must not be {@literal null} + */ public MappingCosmosConverter( MappingContext, CosmosPersistentProperty> mappingContext, @Qualifier(Constants.OBJECTMAPPER_BEAN_NAME) ObjectMapper objectMapper) { this.mappingContext = mappingContext; this.conversionService = new GenericConversionService(); - this.objectMapper = objectMapper == null ? ObjectMapperFactory.getObjectMapper() : - objectMapper; + this.objectMapper = objectMapper == null ? ObjectMapperFactory.getObjectMapper() + : objectMapper; } @Override @@ -78,8 +86,10 @@ private R readInternal(final CosmosPersistentEntity entity, Class type return objectMapper.readValue(jsonObject.toString(), type); } catch (IOException e) { - throw new IllegalStateException("Failed to read the source document " + cosmosItemProperties.toJson() - + " to target type " + type, e); + throw new IllegalStateException("Failed to read the source document " + + cosmosItemProperties.toJson() + + " to target type " + + type, e); } } @@ -89,6 +99,13 @@ public void write(Object sourceEntity, CosmosItemProperties document) { throw new UnsupportedOperationException("The feature is not implemented yet"); } + /** + * To write source entity as a cosmos item + * @param sourceEntity must not be {@literal null} + * @return CosmosItemProperties + * @throws MappingException no mapping metadata for entity type + * @throws CosmosDBAccessException fail to map document value + */ public CosmosItemProperties writeCosmosItemProperties(Object sourceEntity) { if (sourceEntity == null) { return null; @@ -98,7 +115,8 @@ public CosmosItemProperties writeCosmosItemProperties(Object sourceEntity) { mappingContext.getPersistentEntity(sourceEntity.getClass()); if (persistentEntity == null) { - throw new MappingException("no mapping metadata for entity type: " + sourceEntity.getClass().getName()); + throw new MappingException("no mapping metadata for entity type: " + + sourceEntity.getClass().getName()); } final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity); @@ -121,6 +139,10 @@ public CosmosItemProperties writeCosmosItemProperties(Object sourceEntity) { return cosmosItemProperties; } + /** + * To get application context + * @return ApplicationContext + */ public ApplicationContext getApplicationContext() { return this.applicationContext; } @@ -135,6 +157,10 @@ public ConversionService getConversionService() { return conversionService; } + /** + * To get mapping context + * @return MappingContext + */ public MappingContext, CosmosPersistentProperty> getMappingContext() { return mappingContext; } @@ -146,7 +172,7 @@ private ConvertingPropertyAccessor getPropertyAccessor(Object entity) { Assert.notNull(entityInformation, "EntityInformation should not be null."); final PersistentPropertyAccessor accessor = entityInformation.getPropertyAccessor(entity); - return new ConvertingPropertyAccessor<> (accessor, conversionService); + return new ConvertingPropertyAccessor<>(accessor, conversionService); } /** @@ -164,8 +190,7 @@ public static Object toCosmosDbValue(Object fromPropertyValue) { if (fromPropertyValue instanceof Date) { fromPropertyValue = ((Date) fromPropertyValue).getTime(); - } else - if (fromPropertyValue instanceof ZonedDateTime) { + } else if (fromPropertyValue instanceof ZonedDateTime) { fromPropertyValue = ((ZonedDateTime) fromPropertyValue) .format(DateTimeFormatter.ofPattern(ISO_8601_COMPATIBLE_DATE_PATTERN)); } else if (fromPropertyValue instanceof Enum) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java index e4c03564d569..7cdef7ced6f3 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java @@ -9,6 +9,9 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +/** + * Factory class for object mapper + */ public class ObjectMapperFactory { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @@ -19,6 +22,10 @@ public class ObjectMapperFactory { OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } + /** + * To get object mapper + * @return ObjectMapper + */ public static ObjectMapper getObjectMapper() { return OBJECT_MAPPER; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java new file mode 100644 index 000000000000..dc67fc729470 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the converter classes of cosmos db + */ +package com.microsoft.azure.spring.data.cosmosdb.core.convert; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java index 95b4b036d240..c28b1f6ed1f8 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java @@ -21,6 +21,9 @@ import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter.toCosmosDbValue; +/** + * Base class for generating sql query + */ public abstract class AbstractQueryGenerator { protected AbstractQueryGenerator() { @@ -43,7 +46,8 @@ private String generateUnaryQuery(@NonNull Criteria criteria) { } private String generateBinaryQuery(@NonNull Criteria criteria, @NonNull List> parameters) { - Assert.isTrue(criteria.getSubjectValues().size() == 1, "Binary criteria should have only one subject value"); + Assert.isTrue(criteria.getSubjectValues().size() == 1, + "Binary criteria should have only one subject value"); Assert.isTrue(CriteriaType.isBinary(criteria.getType()), "Criteria type should be binary operation"); final String subject = criteria.getSubject(); @@ -76,7 +80,8 @@ private String generateBetween(@NonNull Criteria criteria, @NonNull List subjects = sort.stream().map(this::getParameter).collect(Collectors.toList()); - return queryTail + " " + String.join(",", subjects); + return queryTail + + " " + + String.join(",", subjects); } @NonNull @@ -207,8 +217,8 @@ protected SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query, sqlParameters.addAll( parameters.stream() - .map(p -> new com.azure.data.cosmos.SqlParameter("@" + p.getValue0(), - toCosmosDbValue(p.getValue1()))) + .map(p -> new com.azure.data.cosmos.SqlParameter("@" + + p.getValue0(), toCosmosDbValue(p.getValue1()))) .collect(Collectors.toList()) ); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java index 9d02ed74c025..bddecf136e4c 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java @@ -5,6 +5,9 @@ import com.azure.data.cosmos.SqlQuerySpec; import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +/** + * Generate count query + */ public class CountQueryGenerator extends AbstractQueryGenerator implements QuerySpecGenerator { @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java index 349b072acac4..3296e23e89b2 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java @@ -5,8 +5,13 @@ import com.azure.data.cosmos.SqlQuerySpec; import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +/** + * Generate sql find query + */ public class FindQuerySpecGenerator extends AbstractQueryGenerator implements QuerySpecGenerator { - + /** + * Initialization + */ public FindQuerySpecGenerator() { } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java index dcdd2e8d8257..a1cf9e8e0e2f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java @@ -5,6 +5,9 @@ import com.azure.data.cosmos.SqlQuerySpec; import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +/** + * Interface of generating SqlQuerySpec + */ public interface QuerySpecGenerator { /** diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java new file mode 100644 index 000000000000..b67e5a92e7e3 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the generator classes of cosmos db + */ +package com.microsoft.azure.spring.data.cosmosdb.core.generator; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java index 12e69c6f0840..89ccc99ada71 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java @@ -12,23 +12,39 @@ import org.springframework.data.util.TypeInformation; import org.springframework.expression.spel.support.StandardEvaluationContext; - +/** + * Simple value object to capture information of {@link CosmosPersistentProperty}s. + */ public class BasicCosmosPersistentEntity extends BasicPersistentEntity implements CosmosPersistentEntity, ApplicationContextAware { private final StandardEvaluationContext context; + /** + * Creates a new {@link BasicCosmosPersistentEntity} from the given {@link TypeInformation}. + * + * @param typeInformation must not be {@literal null}. + */ public BasicCosmosPersistentEntity(TypeInformation typeInformation) { super(typeInformation); this.context = new StandardEvaluationContext(); } + /** + * To set application context + * @param applicationContext must not be {@literal null}. + * @throws BeansException the bean exception + */ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context.addPropertyAccessor(new BeanFactoryAccessor()); context.setBeanResolver(new BeanFactoryResolver(applicationContext)); context.setRootObject(applicationContext); } + /** + * To get collection of entity + * @return String + */ public String getCollection() { return ""; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java index fc94b094e8c3..7b5fd02c173e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java @@ -9,10 +9,19 @@ import org.springframework.data.mapping.model.Property; import org.springframework.data.mapping.model.SimpleTypeHolder; - +/** + * Special {@link CosmosPersistentProperty} that takes annotations at a property into account. + */ public class BasicCosmosPersistentProperty extends AnnotationBasedPersistentProperty implements CosmosPersistentProperty { + /** + * Creates a new {@link BasicCosmosPersistentProperty}. + * + * @param property must not be {@literal null}. + * @param owner must not be {@literal null}. + * @param simpleTypeHolder must not be {@literal null}. + */ public BasicCosmosPersistentProperty(Property property, CosmosPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { super(property, owner, simpleTypeHolder); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java index 0f92ab6fb43d..f2c1c7bf2bb4 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java @@ -9,7 +9,10 @@ import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.util.TypeInformation; - +/** + * Class to build mapping metadata and thus create instances of {@link BasicCosmosPersistentEntity} and + * {@link CosmosPersistentProperty}. + */ public class CosmosMappingContext extends AbstractMappingContext, CosmosPersistentProperty> { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java index 1f78834085f2..3418648de325 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java @@ -5,13 +5,27 @@ import org.springframework.data.mapping.PersistentEntity; - +/** + * Represents a cosmos persistent entity. + */ public interface CosmosPersistentEntity extends PersistentEntity { - + /** + * To get collection + * @return String + * @deprecated use {@link #getContainer()} instead + */ @Deprecated String getCollection(); + /** + * To get container of entity + * @return String + */ String getContainer(); + /** + * To get language + * @return String + */ String getLanguage(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java index 33610e291715..31ce39f31037 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java @@ -5,6 +5,8 @@ import org.springframework.data.mapping.PersistentProperty; - +/** + * Interface for cosmos persistent property + */ public interface CosmosPersistentProperty extends PersistentProperty { } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java index 5a7ff3c06957..79cd9534e794 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java @@ -5,19 +5,41 @@ import com.microsoft.azure.spring.data.cosmosdb.Constants; import org.springframework.data.annotation.Persistent; -import java.lang.annotation.*; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +/** + * Annotation of cosmos document + */ @Persistent @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Document { - + /** + * To set collection name + * @return String + */ String collection() default Constants.DEFAULT_COLLECTION_NAME; + /** + * To set request unit + * @return default as 4000 + */ String ru() default Constants.DEFAULT_REQUEST_UNIT; + /** + * To set the ttl of container level + * @return default as no ttl + */ int timeToLive() default Constants.DEFAULT_TIME_TO_LIVE; + /** + * To set if create collection automatically + * @return default as true + */ boolean autoCreateCollection() default Constants.DEFAULT_AUTO_CREATE_CONTAINER; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java index a64cf437f54c..e578cdb40933 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java @@ -6,18 +6,42 @@ import com.microsoft.azure.spring.data.cosmosdb.Constants; import org.springframework.data.annotation.Persistent; -import java.lang.annotation.*; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +/** + * Annotation for document indexing policy + */ @Persistent @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface DocumentIndexingPolicy { + /** + * To set automatic indexing + * @return default as true + */ boolean automatic() default Constants.DEFAULT_INDEXINGPOLICY_AUTOMATIC; + /** + * To set indexing mode + * + * @return IndexingMode + */ IndexingMode mode() default IndexingMode.CONSISTENT; // Enum is not really compile time constant + /** + * To include paths + * @return String[] + */ String[] includePaths() default {}; + /** + * To exclude paths + * @return String[] + */ String[] excludePaths() default {}; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java index 409a80317ca4..6ae69dd61509 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java @@ -2,8 +2,15 @@ // Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.mapping; -import java.lang.annotation.*; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +/** + * Interface for type partition key + */ @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java new file mode 100644 index 000000000000..e7a0f48b4da8 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the mapping classes of cosmos persistent entities + */ +package com.microsoft.azure.spring.data.cosmosdb.core.mapping; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java new file mode 100644 index 000000000000..0a5a2dee562e --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the core classes of cosmos db, includes converters, + * query generators and mapping to cosmos entities + */ +package com.microsoft.azure.spring.data.cosmosdb.core; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java index 730d7142332e..2c0910740750 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java @@ -1,8 +1,5 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for - * license information. - */ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.query; import org.springframework.data.domain.PageImpl; @@ -11,6 +8,11 @@ import java.util.List; import java.util.Objects; +/** + * {@code CosmosPageImpl} implementation. + * + * @param the type of which the CosmosPageImpl consists. + */ public class CosmosPageImpl extends PageImpl { private static final long serialVersionUID = 5294396337522314504L; @@ -20,6 +22,14 @@ public class CosmosPageImpl extends PageImpl { // Storing the offset of current page, helps to check hasNext and next values private long offset; + /** + * Constructor of {@code CosmosPageImpl}. + * + * @param content the content of this page, must not be {@literal null}. + * @param pageable the paging information, must not be {@literal null}. + * @param total amount of items available. The total might be adapted considering the length of the content + * given, if it is going to be the content of the last page. This is in place to mitigate inconsistencies. + */ public CosmosPageImpl(List content, Pageable pageable, long total) { super(content, pageable, total); this.offset = pageable.getOffset(); @@ -37,7 +47,8 @@ public long getTotalElements() { @Override public boolean hasNext() { - return this.offset + getContent().size() < getTotalElements(); + return this.offset + + getContent().size() < getTotalElements(); } @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java index 58a2dc34c716..9bb916889105 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java @@ -1,8 +1,5 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for - * license information. - */ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.query; import com.azure.data.cosmos.FeedResponse; @@ -25,11 +22,26 @@ public class CosmosPageRequest extends PageRequest { // Request continuation token used to resume query private String requestContinuation; + /** + * Creates a new {@link PageRequest} with unsorted parameters applied. + * + * @param page zero-based page index, must not be negative. + * @param size the size of the page to be returned, must be greater than 0. + * @param requestContinuation must not be {@literal null}. + */ public CosmosPageRequest(int page, int size, String requestContinuation) { super(page, size, Sort.unsorted()); this.requestContinuation = requestContinuation; } + /** + * Creates a new {@link CosmosPageRequest} with sort parameters applied. + * + * @param page zero-based page index, must not be negative. + * @param size the size of the page to be returned, must be greater than 0. + * @param sort must not be {@literal null}, use {@link Sort#unsorted()} instead. + * @param requestContinuation must not be {@literal null}. + */ public CosmosPageRequest(int page, int size, String requestContinuation, Sort sort) { super(page, size, sort); this.requestContinuation = requestContinuation; @@ -48,10 +60,29 @@ private CosmosPageRequest(long offset, int page, int size, String requestContinu this.requestContinuation = requestContinuation; } + /** + * Creates a new {@link CosmosPageRequest} + * + * @param page zero-based page index, must not be negative. + * @param size the size of the page to be returned, must be greater than 0. + * @param requestContinuation cannot be null + * @param sort cannot be null + * @return CosmosPageRequest + */ public static CosmosPageRequest of(int page, int size, String requestContinuation, Sort sort) { return new CosmosPageRequest(0, page, size, requestContinuation, sort); } + /** + * Creates a new {@link CosmosPageRequest} + * + * @param offset cannot be null + * @param page zero-based page index, must not be negative. + * @param size the size of the page to be returned, must be greater than 0. + * @param requestContinuation cannot be null + * @param sort cannot be null + * @return CosmosPageRequest + */ public static CosmosPageRequest of(long offset, int page, int size, String requestContinuation, Sort sort) { return new CosmosPageRequest(offset, page, size, requestContinuation, sort); } @@ -67,6 +98,10 @@ public long getOffset() { return offset; } + /** + * To get request continuation + * @return String + */ public String getRequestContinuation() { return this.requestContinuation; } @@ -75,7 +110,8 @@ public String getRequestContinuation() { public int hashCode() { int result = super.hashCode(); - result = 31 * result + (requestContinuation != null ? requestContinuation.hashCode() : 0); + result = 31 * result + + (requestContinuation != null ? requestContinuation.hashCode() : 0); return result; } @@ -92,9 +128,10 @@ public boolean equals(Object obj) { final CosmosPageRequest that = (CosmosPageRequest) obj; - final boolean continuationTokenEquals = requestContinuation != null ? - requestContinuation.equals(that.requestContinuation) : that.requestContinuation == null; + final boolean continuationTokenEquals = requestContinuation != null + ? requestContinuation.equals(that.requestContinuation) : that.requestContinuation == null; - return continuationTokenEquals && super.equals(that); + return continuationTokenEquals + && super.equals(that); } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java index 2f4c2ab64622..5a0d7b8c5a31 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java @@ -1,8 +1,5 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for - * license information. - */ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.query; import org.springframework.lang.NonNull; @@ -10,25 +7,44 @@ import java.util.ArrayList; import java.util.List; -public class Criteria { +/** + * Class of criteria + */ +public final class Criteria { private String subject; private List subjectValues; private final CriteriaType type; private final List subCriteria; + /** + * To get subject + * @return subject value + */ public String getSubject() { return subject; } + /** + * To get CriteriaType + * @return CriteriaType + */ public List getSubjectValues() { return subjectValues; } + /** + * To get CriteriaType + * @return CriteriaType + */ public CriteriaType getType() { return type; } + /** + * To get sub criteria + * @return List of sub criteria + */ public List getSubCriteria() { return subCriteria; } @@ -38,6 +54,13 @@ private Criteria(CriteriaType type) { this.subCriteria = new ArrayList<>(); } + /** + * To get a criteria instance with subject + * @param type CriteriaType + * @param subject subject + * @param values subject value + * @return Criteria instance + */ public static Criteria getInstance(CriteriaType type, @NonNull String subject, @NonNull List values) { final Criteria criteria = new Criteria(type); @@ -47,6 +70,13 @@ public static Criteria getInstance(CriteriaType type, @NonNull String subject, @ return criteria; } + /** + * To get a criteria instance with sub criteria + * @param type CriteriaType + * @param left Criteria + * @param right Criteria + * @return Criteria instance + */ public static Criteria getInstance(CriteriaType type, @NonNull Criteria left, @NonNull Criteria right) { final Criteria criteria = new Criteria(type); @@ -56,6 +86,11 @@ public static Criteria getInstance(CriteriaType type, @NonNull Criteria left, @N return criteria; } + /** + * To get a new criteria instance + * @param type CriteriaType + * @return Criteria instance + */ public static Criteria getInstance(CriteriaType type) { return new Criteria(type); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java index 96126b6fdbe3..caf6c927875e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java @@ -1,8 +1,5 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for - * license information. - */ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.query; import org.springframework.lang.NonNull; @@ -13,6 +10,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Enum of criteria type + */ public enum CriteriaType { ALL(""), @@ -71,6 +71,10 @@ public enum CriteriaType { this.sqlKeyword = sqlKeyword; } + /** + * To get sql keyword + * @return String + */ public String getSqlKeyword() { return sqlKeyword; } @@ -95,11 +99,20 @@ public static boolean isPartTypeSupported(@NonNull Part.Type partType) { return PART_TREE_TYPE_TO_CRITERIA.containsKey(partType); } + /** + * Convert to criteria type. + * + * @param partType PartType to be converted. + * @return CriteriaType + * @throws UnsupportedOperationException for unsupported part type + */ + @SuppressWarnings("") public static CriteriaType toCriteriaType(@NonNull Part.Type partType) { final CriteriaType criteriaType = PART_TREE_TYPE_TO_CRITERIA.get(partType); if (criteriaType == null) { - throw new UnsupportedOperationException("Unsupported part type: " + partType); + throw new UnsupportedOperationException("Unsupported part type: " + + partType); } return criteriaType; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java index 6927e81b4dc4..8adfb92d93b7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java @@ -1,8 +1,5 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE in the project root for - * license information. - */ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.microsoft.azure.spring.data.cosmosdb.core.query; import org.springframework.data.domain.Pageable; @@ -13,6 +10,9 @@ import java.util.List; import java.util.Optional; +/** + * Class for document query + */ public class DocumentQuery { private final Criteria criteria; @@ -21,22 +21,48 @@ public class DocumentQuery { private Pageable pageable = Pageable.unpaged(); + /** + * Initialization + * + * @param criteria object + */ public DocumentQuery(@NonNull Criteria criteria) { this.criteria = criteria; } + /** + * To get Criteria object + * + * @return Criteria + */ public Criteria getCriteria() { return criteria; } + /** + * To get Sort object + * + * @return Sort + */ public Sort getSort() { return sort; } + /** + * To get Pageable object + * + * @return Pageable + */ public Pageable getPageable() { return pageable; } + /** + * With Sort + * + * @param sort Sort + * @return DocumentQuery object + */ public DocumentQuery with(@NonNull Sort sort) { if (sort.isSorted()) { this.sort = sort.and(this.sort); @@ -45,6 +71,12 @@ public DocumentQuery with(@NonNull Sort sort) { return this; } + /** + * With Sort + * + * @param pageable Sort + * @return DocumentQuery object + */ public DocumentQuery with(@NonNull Pageable pageable) { Assert.notNull(pageable, "pageable should not be null"); @@ -82,6 +114,11 @@ public boolean isCrossPartitionQuery(@NonNull List partitionKeys) { .orElse(hasKeywordOr()); } + /** + * To get criteria by type + * @param criteriaType the criteria type + * @return Optional + */ public Optional getCriteriaByType(@NonNull CriteriaType criteriaType) { return getCriteriaByType(criteriaType, this.criteria); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java new file mode 100644 index 000000000000..bbd03f8b278f --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the query classes of cosmos db document + */ +package com.microsoft.azure.spring.data.cosmosdb.core.query; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java index 262753f211fa..3aea8e557a7f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java @@ -4,12 +4,26 @@ import org.springframework.dao.DataAccessException; +/** + * General exception for illegal configuration of cosmosdb + */ public class ConfigurationException extends DataAccessException { + /** + * Construct a {@code IllegalQueryException} with the specified detail message. + * @param msg the detail message + */ public ConfigurationException(String msg) { super(msg); } + /** + * Construct a {@code IllegalQueryException} with the specified detail message + * and nested exception. + * + * @param msg the detail message + * @param cause the nested exception + */ public ConfigurationException(String msg, Throwable cause) { super(msg, cause); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java index 4cf4d2cd99e5..f20791008ab8 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java @@ -19,11 +19,21 @@ public class CosmosDBAccessException extends DataAccessException { protected final CosmosClientException cosmosClientException; + /** + * Construct a {@code CosmosDBAccessException} with the specified detail message. + * @param msg the detail message + */ public CosmosDBAccessException(String msg) { super(msg); this.cosmosClientException = null; } + /** + * Construct a {@code CosmosDBAccessException} with the specified detail message. + * and nested exception. + * @param msg the detail message + * @param cause the nested Throwable + */ public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); if (cause instanceof CosmosClientException) { @@ -33,6 +43,13 @@ public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) } } + /** + * Construct a {@code CosmosDBAccessException} with the specified detail message + * and nested exception. + * + * @param msg the detail message + * @param cause the nested exception + */ public CosmosDBAccessException(@Nullable String msg, @Nullable Exception cause) { super(msg, cause); this.cosmosClientException = cause instanceof CosmosClientException @@ -40,6 +57,10 @@ public CosmosDBAccessException(@Nullable String msg, @Nullable Exception cause) : null; } + /** + * To get exception object for cosmos client + * @return CosmosClientException + */ public CosmosClientException getCosmosClientException() { return cosmosClientException; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java index 049a153f400c..4e11eca0c4e6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java @@ -8,8 +8,20 @@ import reactor.core.Exceptions; import reactor.core.publisher.Mono; +/** + * To handle and throw a cosmosdb exception when access the database + */ public class CosmosDBExceptionUtils { + /** + * To throw a CosmosDBAccessException + * + * @param message the detail message + * @param throwable exception + * @param type class of Mono + * @return Mono instance + * @throws CosmosDBAccessException for operations on cosmosdb + */ public static Mono exceptionHandler(String message, Throwable throwable) { if (StringUtils.isEmpty(message)) { message = "Failed to access cosmosdb database"; @@ -19,6 +31,14 @@ public static Mono exceptionHandler(String message, Throwable throwable) throw new CosmosDBAccessException(message, unwrappedThrowable); } + /** + * To find an exceptionHandler for a excetption and return empty Mono if the exception status code is not found + * + * @param message the detail message + * @param throwable exception + * @param type class of Mono + * @return Mono instance + */ public static Mono findAPIExceptionHandler(String message, Throwable throwable) { // Unwrap the exception in case if it is a reactive exception final Throwable unwrappedThrowable = Exceptions.unwrap(throwable); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java index 62583a7d891a..d0230725cf97 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java @@ -5,11 +5,26 @@ import org.springframework.dao.DataAccessException; import org.springframework.lang.Nullable; +/** + * General exception for illegal creation of cosmosdb + */ public class DatabaseCreationException extends DataAccessException { + + /** + * Construct a {@code IllegalQueryException} with the specified detail message. + * @param msg the detail message + */ public DatabaseCreationException(String msg) { super(msg); } + /** + * Construct a {@code IllegalQueryException} with the specified detail message + * and nested exception. + * + * @param msg the detail message + * @param cause the nested exception + */ public DatabaseCreationException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java index 57de1768a46b..c447f2d5d291 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java @@ -5,11 +5,26 @@ import org.springframework.dao.DataAccessException; import org.springframework.lang.Nullable; +/** + * General exception for illegal collection of cosmosdb + */ public class IllegalCollectionException extends DataAccessException { + + /** + * Construct a {@code IllegalQueryException} with the specified detail message. + * @param msg the detail message + */ public IllegalCollectionException(String msg) { super(msg); } + /** + * Construct a {@code IllegalQueryException} with the specified detail message + * and nested exception. + * + * @param msg the detail message + * @param cause the nested exception + */ public IllegalCollectionException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java index c57868b60251..75c33a0bb5e9 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java @@ -5,11 +5,26 @@ import org.springframework.dao.DataAccessException; import org.springframework.lang.Nullable; +/** + * General exception for illegal query of cosmosdb + */ public class IllegalQueryException extends DataAccessException { + + /** + * Construct a {@code IllegalQueryException} with the specified detail message. + * @param msg the detail message + */ public IllegalQueryException(String msg) { super(msg); } + /** + * Construct a {@code IllegalQueryException} with the specified detail message + * and nested exception. + * + * @param msg the detail message + * @param cause the nested exception + */ public IllegalQueryException(@Nullable String msg, @Nullable Throwable cause) { super(msg, cause); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java new file mode 100644 index 000000000000..a420e54064b7 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the exception classes of cosmos db + */ +package com.microsoft.azure.spring.data.cosmosdb.exception; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java new file mode 100644 index 000000000000..12dc2276157d --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * Cosmosdb class for spring + */ +package com.microsoft.azure.spring.data.cosmosdb; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java index c830cdc9edd2..85274905a3c1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java @@ -11,6 +11,10 @@ import java.util.List; import java.util.Optional; +/** + * Extension of {@link PagingAndSortingRepository} to provide additional methods to retrieve entities + * using the pagination and sorting abstraction. + */ @NoRepositoryBean public interface CosmosRepository extends PagingAndSortingRepository { @@ -26,6 +30,7 @@ public interface CosmosRepository extends PagingAndS /** * Deletes an entity by its id and partition key. + * * @param id must not be {@literal null}. * @param partitionKey partition key value of the entity, must not be null. * @throws IllegalArgumentException in case the given {@code id} is {@literal null}. @@ -34,6 +39,7 @@ public interface CosmosRepository extends PagingAndS /** * Returns list of items in a specific partition + * * @param partitionKey partition key value * @return list of items with partition key value */ diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java index b8119eff78f0..b963adc03fcd 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java @@ -7,7 +7,9 @@ import org.springframework.data.repository.reactive.ReactiveSortingRepository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; - +/** + * Repository interface with search and delete operation + */ @NoRepositoryBean public interface ReactiveCosmosRepository extends ReactiveSortingRepository { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java index d3b805a6ba0c..ba20dd279785 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java @@ -8,7 +8,9 @@ import java.lang.annotation.Annotation; - +/** + * Inherit {@link RepositoryBeanDefinitionRegistrarSupport} class to enable repository and get extension + */ public class CosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java index f46493f4fd4d..2c479f88887b 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java @@ -19,7 +19,10 @@ import java.util.Collection; import java.util.Collections; - +/** + * Configuration extension class based on {@link RepositoryConfigurationExtensionSupport} provide options to set + * repository support. + */ public class CosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { @Override @@ -32,6 +35,10 @@ public String getModulePrefix() { return Constants.COSMOSDB_MODULE_PREFIX; } + /** + * Return the name of the repository factory bean class. + * @return String value of bean name + */ public String getRepositoryFactoryBeanClassName() { return CosmosRepositoryFactoryBean.class.getName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java index 270bb1aacbcf..14eca6637790 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java @@ -10,9 +10,16 @@ import org.springframework.data.repository.config.DefaultRepositoryBaseClass; import org.springframework.data.repository.query.QueryLookupStrategy; -import java.lang.annotation.*; - - +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Interface to enable cosmos repository + */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @@ -20,26 +27,70 @@ @Import(CosmosRepositoriesRegistrar.class) public @interface EnableCosmosRepositories { + /** + * Toset repo value + * @return default as {} + */ String[] value() default {}; + /** + * To set base packages + * @return default as {} + */ String[] basePackages() default {}; + /** + * To set base package class + * @return default as {} + */ Class[] basePackageClasses() default {}; + /** + * To include filters + * @return default as {} + */ Filter[] includeFilters() default {}; + /** + * To exclude filters + * @return default as {} + */ Filter[] excludeFilters() default {}; + /** + * To set repo Implement postfix + * @return default as "Impl" + */ String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX; + /** + * To set the named query location + * @return default as "" + */ String namedQueriesLocation() default ""; + /** + * To set query look up strategy + * @return QueryLookupStrategy.Key + */ QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND; + /** + * To set factory bean class of repo + * @return default value is ReactiveCosmosRepositoryFactoryBean.class + */ Class repositoryFactoryBeanClass() default CosmosRepositoryFactoryBean.class; + /** + * To set base class of repo + * @return default value is DefaultRepositoryBaseClass.class + */ Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; + /** + * To set if consider nested repositories + * @return default value is false + */ boolean considerNestedRepositories() default false; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java index cd22140f59f5..7eb05a311832 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java @@ -17,7 +17,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - +/** + * Interface to enable reactive cosmos repository + */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @@ -25,26 +27,70 @@ @Import(ReactiveCosmosRepositoriesRegistrar.class) public @interface EnableReactiveCosmosRepositories { + /** + * Toset repo value + * @return default as {} + */ String[] value() default {}; + /** + * To set base packages + * @return default as {} + */ String[] basePackages() default {}; + /** + * To set base package class + * @return default as {} + */ Class[] basePackageClasses() default {}; + /** + * To include filters + * @return default as {} + */ Filter[] includeFilters() default {}; + /** + * To exclude filters + * @return default as {} + */ Filter[] excludeFilters() default {}; + /** + * To set repo Implement postfix + * @return default as "Impl" + */ String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX; + /** + * To set the named query location + * @return default as "" + */ String namedQueriesLocation() default ""; + /** + * To set query look up strategy + * @return QueryLookupStrategy.Key + */ QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND; + /** + * To set factory bean class of repo + * @return default value is ReactiveCosmosRepositoryFactoryBean.class + */ Class repositoryFactoryBeanClass() default ReactiveCosmosRepositoryFactoryBean.class; + /** + * To set base class of repo + * @return default value is DefaultRepositoryBaseClass.class + */ Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; + /** + * To set if consider nested repositories + * @return default value is false + */ boolean considerNestedRepositories() default false; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java index 569a2d8666d3..bbcb6b2b84f4 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java @@ -8,7 +8,9 @@ import java.lang.annotation.Annotation; - +/** + * Inherit {@link RepositoryBeanDefinitionRegistrarSupport} class to enable repository and get extension + */ public class ReactiveCosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java index 8926d4917e62..e9a5b87faa59 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java @@ -19,7 +19,10 @@ import java.util.Collection; import java.util.Collections; - +/** + * Configuration extension class based on {@link RepositoryConfigurationExtensionSupport} provide options to set + * reactive repository support. + */ public class ReactiveCosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { @Override @@ -32,6 +35,10 @@ public String getModulePrefix() { return Constants.COSMOSDB_MODULE_PREFIX; } + /** + * Return the name of the repository factory bean class. + * @return String value of bean name + */ public String getRepositoryFactoryBeanClassName() { return ReactiveCosmosRepositoryFactoryBean.class.getName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java new file mode 100644 index 000000000000..7891cc7d30ad --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the config classes of setting up cosmosdb repositories + */ +package com.microsoft.azure.spring.data.cosmosdb.repository.config; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java new file mode 100644 index 000000000000..fa885616b308 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the support, query and config classes of setting up cosmosdb repositories + */ +package com.microsoft.azure.spring.data.cosmosdb.repository; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java index 172bca42f779..55e012d185e6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java @@ -7,16 +7,31 @@ import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; +/** + * Abstract class for cosmos query. + */ public abstract class AbstractCosmosQuery implements RepositoryQuery { private final CosmosQueryMethod method; private final CosmosOperations operations; + /** + * Initialization + * + * @param method CosmosQueryMethod + * @param operations CosmosOperations + */ public AbstractCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) { this.method = method; this.operations = operations; } + /** + * Executes the {@link AbstractCosmosQuery} with the given parameters. + * + * @param parameters must not be {@literal null}. + * @return execution result. Can be {@literal null}. + */ public Object execute(Object[] parameters) { final CosmosParameterAccessor accessor = new CosmosParameterParameterAccessor(method, parameters); final DocumentQuery query = createQuery(accessor); @@ -41,6 +56,11 @@ private CosmosQueryExecution getExecution(CosmosParameterAccessor accessor) { } } + /** + * Get method of query + * + * @return CosmosQueryMethod + */ public CosmosQueryMethod getQueryMethod() { return method; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java index 437ce543798e..8b0d92e6f18a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java @@ -7,17 +7,32 @@ import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; +/** + * Abstract class for reactive cosmos query. + */ public abstract class AbstractReactiveCosmosQuery implements RepositoryQuery { private final ReactiveCosmosQueryMethod method; private final ReactiveCosmosOperations operations; + /** + * Initialization + * + * @param method ReactiveCosmosQueryMethod + * @param operations ReactiveCosmosOperations + */ public AbstractReactiveCosmosQuery(ReactiveCosmosQueryMethod method, ReactiveCosmosOperations operations) { this.method = method; this.operations = operations; } + /** + * Executes the {@link AbstractReactiveCosmosQuery} with the given parameters. + * + * @param parameters must not be {@literal null}. + * @return execution result. Can be {@literal null}. + */ public Object execute(Object[] parameters) { final ReactiveCosmosParameterAccessor accessor = new ReactiveCosmosParameterParameterAccessor(method, parameters); @@ -37,8 +52,8 @@ private ReactiveCosmosQueryExecution getExecution(ReactiveCosmosParameterAccesso if (isDeleteQuery()) { return new ReactiveCosmosQueryExecution.DeleteExecution(operations); } else if (method.isPageQuery()) { - throw new IllegalArgumentException("Paged Query is not supported by reactive cosmos " + - "db"); + throw new IllegalArgumentException("Paged Query is not supported by reactive cosmos " + + "db"); } else if (isExistsQuery()) { return new ReactiveCosmosQueryExecution.ExistsExecution(operations); } else { @@ -46,6 +61,11 @@ private ReactiveCosmosQueryExecution getExecution(ReactiveCosmosParameterAccesso } } + /** + * Get method of query + * + * @return ReactiveCosmosQueryMethod + */ public ReactiveCosmosQueryMethod getQueryMethod() { return method; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java index 29ce6a4c4923..af36f066e50f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java @@ -4,14 +4,22 @@ import org.springframework.data.repository.core.EntityMetadata; +/** + * Metadata class to describe cosmos entity includes domain type and container information + */ public interface CosmosEntityMetadata extends EntityMetadata { /** - * Use getContainerName() instead - * @return container name + * Get collection name from the given entity + * @return String + * @deprecated use {@link #getContainerName()} instead */ @Deprecated String getCollectionName(); + /** + * Get container name from the given entity + * @return String + */ String getContainerName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java index cebfc1f6a57e..d667df89a993 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java @@ -5,8 +5,16 @@ import org.springframework.core.MethodParameter; import org.springframework.data.repository.query.Parameter; +/** + * A single cosmos parameter of a query method. + */ public class CosmosParameter extends Parameter { + /** + * Creates a new {@link CosmosParameter} for the given {@link MethodParameter}. + * + * @param parameter must not be {@literal null}. + */ public CosmosParameter(MethodParameter parameter) { super(parameter); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java index 26916c55cf2e..0cb40ad1db77 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java @@ -4,6 +4,15 @@ import org.springframework.data.repository.query.ParameterAccessor; +/** + * Interface to access method parameters. Allows dedicated access to parameters of special types and expose api to read + * values. + */ public interface CosmosParameterAccessor extends ParameterAccessor { + + /** + * Get values of method parameters + * @return Object[] + */ Object[] getValues(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java index 5a0ce5186b88..2ce2d081ec3e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java @@ -7,11 +7,20 @@ import java.util.Arrays; import java.util.List; +/** + * {@link ParametersParameterAccessor} implementation and store all special parameters in a List. + */ public class CosmosParameterParameterAccessor extends ParametersParameterAccessor implements CosmosParameterAccessor { private final List values; + /** + * Creates a new {@link CosmosParameterParameterAccessor}. + * + * @param method must not be {@literal null}. + * @param values must not be {@literal null}. + */ public CosmosParameterParameterAccessor(CosmosQueryMethod method, Object[] values) { super(method.getParameters(), values); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java index 39017da4d9df..55386969f85d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java @@ -8,8 +8,16 @@ import java.lang.reflect.Method; import java.util.List; +/** + * Method parameters that have to be bound to query parameters or applied to the query independently. + */ public class CosmosParameters extends Parameters { + /** + * Creates a new instance of {@link CosmosParameters}. + * + * @param method must not be {@literal null}. + */ public CosmosParameters(Method method) { super(method); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java index f9bbf1133a98..828917f1b2d1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java @@ -19,14 +19,24 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -// TODO: String based query, based on how cosmosdb provides. -// StringCosmosQuery class, -// How to bind values to the query. if CosmosDb already has binding capability, if not we would have to do it here in -// some creative way.query creator are associated with part tree queries, +/** + * TODO: String based query, based on how cosmosdb provides. + * StringCosmosQuery class, + * How to bind values to the query. if CosmosDb already has binding capability, if not we would have to do it here in + * some creative way.query creator are associated with part tree queries, + */ public class CosmosQueryCreator extends AbstractQueryCreator { private final MappingContext mappingContext; + /** + * Creates a new {@link CosmosQueryCreator}. {@link CosmosParameterAccessor} is used to hand actual + * parameter values into the callback methods as well as to apply dynamic sorting via a {@link Sort} parameter. + * + * @param tree must not be {@literal null}. + * @param accessor must not be {@literal null}. + * @param mappingContext must not be {@literal null}. + */ public CosmosQueryCreator(PartTree tree, CosmosParameterAccessor accessor, MappingContext mappingContext) { super(tree, accessor); @@ -55,7 +65,8 @@ protected Criteria create(Part part, Iterator parameters) { final List values = new ArrayList<>(); if (CriteriaType.isPartTypeUnSupported(type)) { - throw new UnsupportedOperationException("Unsupported keyword: " + type); + throw new UnsupportedOperationException("Unsupported keyword: " + + type); } for (int i = 0; i < part.getNumberOfArguments(); i++) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java index 4b34f6516a3c..6d3ae6f3ed6f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java @@ -7,9 +7,24 @@ import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; import org.springframework.data.domain.Pageable; +/** + * Interface to execute cosmos query operations + */ public interface CosmosQueryExecution { + + /** + * Declare an execute function for different operations to call + * + * @param query document query operation + * @param type domain type + * @param container container to conduct query + * @return Object according to execution result + */ Object execute(DocumentQuery query, Class type, String container); + /** + * Container operation implementation to execute a container name query + */ final class ContainerExecution implements CosmosQueryExecution { private final CosmosOperations operations; @@ -24,6 +39,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * Find operation implementation to execute a find query + */ final class MultiEntityExecution implements CosmosQueryExecution { private final CosmosOperations operations; @@ -38,6 +56,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * exist operation implementation to execute a exists query + */ final class ExistsExecution implements CosmosQueryExecution { private final CosmosOperations operations; @@ -52,6 +73,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * delete operation implementation to execute a delete query + */ final class DeleteExecution implements CosmosQueryExecution { private final CosmosOperations operations; @@ -66,6 +90,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * paginationQuery operation implementation to execute a paginationQuery query + */ final class PagedExecution implements CosmosQueryExecution { private final CosmosOperations operations; private final Pageable pageable; @@ -77,9 +104,10 @@ public PagedExecution(CosmosOperations operations, Pageable pageable) { @Override public Object execute(DocumentQuery query, Class type, String container) { - if (pageable.getPageNumber() != 0 && !(pageable instanceof CosmosPageRequest)) { - throw new IllegalStateException("Not the first page but Pageable is not a valid " + - "CosmosPageRequest, requestContinuation is required for non first page request"); + if (pageable.getPageNumber() != 0 + && !(pageable instanceof CosmosPageRequest)) { + throw new IllegalStateException("Not the first page but Pageable is not a valid " + + "CosmosPageRequest, requestContinuation is required for non first page request"); } query.with(pageable); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java index 4c6c4cfc9455..033b38282c9e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java @@ -10,10 +10,21 @@ import java.lang.reflect.Method; +/** + * Inherit QueryMethod class to generate a method that is designated to execute a finder query. + */ public class CosmosQueryMethod extends QueryMethod { private CosmosEntityMetadata metadata; + /** + * Creates a new {@link CosmosQueryMethod} from the given parameters. Looks up the correct query to use + * for following invocations of the method given. + * + * @param method must not be {@literal null}. + * @param metadata must not be {@literal null}. + * @param factory must not be {@literal null}. + */ public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { super(method, metadata, factory); } @@ -23,7 +34,7 @@ public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionF public EntityMetadata getEntityInformation() { final Class domainType = (Class) getDomainClass(); final CosmosEntityInformation entityInformation = - new CosmosEntityInformation(domainType); + new CosmosEntityInformation(domainType); this.metadata = new SimpleCosmosEntityMetadata(domainType, entityInformation); return this.metadata; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java index 2a5251aec302..6618f5528ef3 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java @@ -8,14 +8,24 @@ import org.apache.commons.lang3.NotImplementedException; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.repository.query.parser.Part; import org.springframework.data.repository.query.parser.PartTree; +/** + * Cosmos query class with {@link PartTree} to parse a {@link String} into a tree or {@link PartTree.OrPart}s consisting + * of simple {@link Part} instances in turn. + */ public class PartTreeCosmosQuery extends AbstractCosmosQuery { private final PartTree tree; private final MappingContext mappingContext; private final ResultProcessor processor; + /** + * Initialization + * @param method CosmosQueryMethod + * @param operations CosmosOperations + */ public PartTreeCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) { super(method, operations); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java index 5a76d5055a7f..7ee24913e199 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java @@ -8,14 +8,24 @@ import org.apache.commons.lang3.NotImplementedException; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.repository.query.parser.Part; import org.springframework.data.repository.query.parser.PartTree; +/** + * Reactive cosmos query class with {@link PartTree} to parse a {@link String} into a tree or {@link PartTree.OrPart}s + * consisting of simple {@link Part} instances in turn. + */ public class PartTreeReactiveCosmosQuery extends AbstractReactiveCosmosQuery { private final PartTree tree; private final MappingContext mappingContext; private final ResultProcessor processor; + /** + * Initialization + * @param method ReactiveCosmosQueryMethod + * @param operations ReactiveCosmosOperations + */ public PartTreeReactiveCosmosQuery(ReactiveCosmosQueryMethod method, ReactiveCosmosOperations operations) { super(method, operations); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java index 5535427db920..62c6b844e12a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java @@ -4,9 +4,22 @@ import org.springframework.data.repository.core.EntityMetadata; +/** + * Metadata class to describe reactive cosmos entity includes domain type and container information + */ public interface ReactiveCosmosEntityMetadata extends EntityMetadata { + + /** + * Get collection name from the given entity + * @return String + * @deprecated use {@link #getContainerName()} instead + */ @Deprecated String getCollectionName(); + /** + * Get container name from the given entity + * @return String + */ String getContainerName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java index e9cbccbb0da9..fc90b7d55de1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java @@ -4,6 +4,15 @@ import org.springframework.data.repository.query.ParameterAccessor; +/** + * Interface to access method parameters. Allows dedicated access to parameters of special types and expose api to read + * values. + */ public interface ReactiveCosmosParameterAccessor extends ParameterAccessor { + + /** + * Get values of method parameters + * @return Object[] + */ Object[] getValues(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java index 68157756fbe0..9d31c6381d32 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java @@ -7,11 +7,21 @@ import java.util.Arrays; import java.util.List; +/** + * {@link ReactiveCosmosParameterParameterAccessor} implementation using a {@link ParametersParameterAccessor} instance + * to find special parameters. + */ public class ReactiveCosmosParameterParameterAccessor extends ParametersParameterAccessor implements ReactiveCosmosParameterAccessor { private final List values; + /** + * Creates a new {@link ReactiveCosmosParameterParameterAccessor}. + * + * @param method must not be {@literal null}. + * @param values must not be {@literal null}. + */ public ReactiveCosmosParameterParameterAccessor(ReactiveCosmosQueryMethod method, Object[] values) { super(method.getParameters(), values); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java index 342ec58e6f60..be36e333bcf7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java @@ -20,10 +20,21 @@ import java.util.Iterator; import java.util.List; +/** + * Class for reactive cosmos query creators that create criteria based queries from a {@link PartTree}. + */ public class ReactiveCosmosQueryCreator extends AbstractQueryCreator { private final MappingContext mappingContext; + /** + * Creates a new {@link ReactiveCosmosQueryCreator}. {@link ReactiveCosmosParameterAccessor} is used to hand actual + * parameter values into the callback methods as well as to apply dynamic sorting via a {@link Sort} parameter. + * + * @param tree must not be {@literal null}. + * @param accessor must not be {@literal null}. + * @param mappingContext must not be {@literal null}. + */ public ReactiveCosmosQueryCreator(PartTree tree, ReactiveCosmosParameterAccessor accessor, MappingContext mappingContext) { super(tree, accessor); @@ -52,7 +63,8 @@ protected Criteria create(Part part, Iterator parameters) { final List values = new ArrayList<>(); if (CriteriaType.isPartTypeUnSupported(type)) { - throw new UnsupportedOperationException("Unsupported keyword: " + type); + throw new UnsupportedOperationException("Unsupported keyword: " + + type); } for (int i = 0; i < part.getNumberOfArguments(); i++) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java index 5ef95b26c625..bf615fae2dbe 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java @@ -5,9 +5,24 @@ import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery; +/** + * Interface to execute reactive cosmos query operations + */ public interface ReactiveCosmosQueryExecution { + + /** + * Declare an execute function for different operations to call + * + * @param query document query operation + * @param type domain type + * @param container container to conduct query + * @return Object according to execution result + */ Object execute(DocumentQuery query, Class type, String container); + /** + * Container operation implementation to execute a container name query + */ final class ContainerExecution implements ReactiveCosmosQueryExecution { private final ReactiveCosmosOperations operations; @@ -22,6 +37,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * Find operation implementation to execute a find query + */ final class MultiEntityExecution implements ReactiveCosmosQueryExecution { private final ReactiveCosmosOperations operations; @@ -36,6 +54,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * Exist operation implementation to execute a exist query + */ final class ExistsExecution implements ReactiveCosmosQueryExecution { private final ReactiveCosmosOperations operations; @@ -50,6 +71,9 @@ public Object execute(DocumentQuery query, Class type, String container) { } } + /** + * Delete operation implementation to execute a delete query + */ final class DeleteExecution implements ReactiveCosmosQueryExecution { private final ReactiveCosmosOperations operations; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java index 468bd6c2e744..288fa02d7564 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java @@ -10,10 +10,21 @@ import java.lang.reflect.Method; +/** + * Inherit from QueryMethod class to execute a finder query. + */ public class ReactiveCosmosQueryMethod extends QueryMethod { private ReactiveCosmosEntityMetadata metadata; + /** + * Creates a new {@link QueryMethod} from the given parameters. Looks up the correct query to use for following + * invocations of the method given. + * + * @param method must not be {@literal null}. + * @param metadata must not be {@literal null}. + * @param factory must not be {@literal null}. + */ public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) { super(method, metadata, factory); } @@ -23,7 +34,7 @@ public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, Pro public EntityMetadata getEntityInformation() { final Class domainType = (Class) getDomainClass(); final CosmosEntityInformation entityInformation = - new CosmosEntityInformation(domainType); + new CosmosEntityInformation(domainType); this.metadata = new SimpleReactiveCosmosEntityMetadata(domainType, entityInformation); return this.metadata; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java index 4e95b54b7f6a..c027a1bc7a50 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java @@ -5,11 +5,20 @@ import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; import org.springframework.util.Assert; +/** + * Metadata class to describe simple cosmos entity includes domain type and cosmos entity information + */ public class SimpleCosmosEntityMetadata implements CosmosEntityMetadata { private final Class type; private final CosmosEntityInformation entityInformation; + /** + * Initialization + * + * @param type the actual domain class type + * @param entityInformation cosmos entity + */ public SimpleCosmosEntityMetadata(Class type, CosmosEntityInformation entityInformation) { Assert.notNull(type, "type must not be null!"); Assert.notNull(entityInformation, "entityInformation must not be null!"); @@ -18,14 +27,29 @@ public SimpleCosmosEntityMetadata(Class type, CosmosEntityInformation getJavaType() { return type; } + /** + * Get collection name of cosmos + * + * @return container name + */ public String getCollectionName() { return entityInformation.getContainerName(); } + /** + * Get container name of cosmos + * + * @return container name + */ public String getContainerName() { return entityInformation.getContainerName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java index 930bbf005596..36294fcdc6ec 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java @@ -5,11 +5,20 @@ import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation; import org.springframework.util.Assert; +/** + * Metadata class to describe simple reactive cosmos entity includes domain type and cosmos entity information + */ public class SimpleReactiveCosmosEntityMetadata implements ReactiveCosmosEntityMetadata { private final Class type; private final CosmosEntityInformation entityInformation; + /** + * Initialization + * + * @param type the actual domain class type + * @param entityInformation cosmos entity + */ public SimpleReactiveCosmosEntityMetadata(Class type, CosmosEntityInformation entityInformation) { Assert.notNull(type, "type must not be null!"); @@ -19,10 +28,20 @@ public SimpleReactiveCosmosEntityMetadata(Class type, CosmosEntityInformation this.entityInformation = entityInformation; } + /** + * Return the actual domain class type + * + * @return type + */ public Class getJavaType() { return type; } + /** + * Get collection name of cosmos + * + * @return container name + */ public String getCollectionName() { return entityInformation.getContainerName(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java new file mode 100644 index 000000000000..18fb93d32872 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the process cosmos queries + */ +package com.microsoft.azure.spring.data.cosmosdb.repository.query; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java index fcaad6bbf7bb..5693c99bda2c 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.List; - +/** + * Class to describe cosmosdb entity + */ public class CosmosEntityInformation extends AbstractEntityInformation { private static final String ETAG = "_etag"; @@ -39,6 +41,11 @@ public class CosmosEntityInformation extends AbstractEntityInformation domainType) { super(domainType); @@ -58,46 +65,99 @@ public CosmosEntityInformation(Class domainType) { this.autoCreateContainer = getIsAutoCreateContainer(domainType); } + /** + * Get the field represented by the supplied id field on the + * specified entity. + * + * @param entity the target object from which to get the field + * @return the id's current value + */ @SuppressWarnings("unchecked") public ID getId(T entity) { return (ID) ReflectionUtils.getField(id, entity); } + /** + * Get id field + * + * @return id + */ public Field getIdField() { return this.id; } + /** + * Get id type + * + * @return class of id type + */ @SuppressWarnings("unchecked") public Class getIdType() { return (Class) id.getType(); } + /** + * Get collection name + * + * @return collection name + * @deprecated Use {@link #getContainerName()} instead + */ @Deprecated public String getCollectionName() { return this.containerName; } + /** + * Get container name + * + * @return container name + */ public String getContainerName() { return this.containerName; } + /** + * Get request unit value + * + * @return request unit + */ public Integer getRequestUnit() { return this.requestUnit; } + /** + * Get timeToLive value + * + * @return timeToLive + */ public Integer getTimeToLive() { return this.timeToLive; } + /** + * Get indexing policy + * + * @return IndexingPolicy + */ @NonNull public IndexingPolicy getIndexingPolicy() { return this.indexingPolicy; } + /** + * Check if is versioned + * + * @return boolean + */ public boolean isVersioned() { return isVersioned; } + /** + * Get the field name represented by the supplied partitionKeyField object + * + * @return partition key field name + */ public String getPartitionKeyFieldName() { if (partitionKeyField == null) { return null; @@ -107,15 +167,33 @@ public String getPartitionKeyFieldName() { } } + /** + * Get the field value represented by the supplied partitionKeyField object on the + * specified entity object. + * + * @param entity the target object from which to get the field + * @return partition key field + */ public String getPartitionKeyFieldValue(T entity) { return partitionKeyField == null ? null : (String) ReflectionUtils.getField(partitionKeyField, entity); } + /** + * Check if auto creating collection is allowed + * + * @return boolean + * @deprecated Use {@link #isAutoCreateContainer()} instead. + */ @Deprecated public boolean isAutoCreateCollection() { return autoCreateContainer; } + /** + * Check if auto creating container is allowed + * + * @return boolean + */ public boolean isAutoCreateContainer() { return autoCreateContainer; } @@ -146,7 +224,8 @@ private Field getIdField(Class domainType) { if (idField == null) { throw new IllegalArgumentException("domain should contain @Id field or field named id"); } else if (idField.getType() != String.class - && idField.getType() != Integer.class && idField.getType() != int.class) { + && idField.getType() != Integer.class + && idField.getType() != int.class) { throw new IllegalArgumentException("type of id field must be String or Integer"); } @@ -158,7 +237,9 @@ private String getContainerName(Class domainType) { final Document annotation = domainType.getAnnotation(Document.class); - if (annotation != null && annotation.collection() != null && !annotation.collection().isEmpty()) { + if (annotation != null + && annotation.collection() != null + && !annotation.collection().isEmpty()) { customContainerName = resolveExpression(annotation.collection()); } @@ -173,11 +254,12 @@ private Field getPartitionKeyField(Class domainType) { if (fields.size() == 1) { partitionKey = fields.get(0); } else if (fields.size() > 1) { - throw new IllegalArgumentException("Azure Cosmos DB supports only one partition key, " + - "only one field with @PartitionKey annotation!"); + throw new IllegalArgumentException("Azure Cosmos DB supports only one partition key, " + + "only one field with @PartitionKey annotation!"); } - if (partitionKey != null && partitionKey.getType() != String.class) { + if (partitionKey != null + && partitionKey.getType() != String.class) { throw new IllegalArgumentException("type of PartitionKey field must be String"); } return partitionKey; @@ -187,7 +269,9 @@ private Integer getRequestUnit(Class domainType) { Integer ru = Integer.parseInt(Constants.DEFAULT_REQUEST_UNIT); final Document annotation = domainType.getAnnotation(Document.class); - if (annotation != null && annotation.ru() != null && !annotation.ru().isEmpty()) { + if (annotation != null + && annotation.ru() != null + && !annotation.ru().isEmpty()) { ru = Integer.parseInt(annotation.ru()); } return ru; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java index 07ca3fe57cba..2ca611f65cd5 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java @@ -22,12 +22,20 @@ import java.lang.reflect.Method; import java.util.Optional; - +/** + * Factory class for cosmos repository contains application context and operations information + */ public class CosmosRepositoryFactory extends RepositoryFactorySupport { private final ApplicationContext applicationContext; private final CosmosOperations cosmosOperations; + /** + * Initialization + * + * @param cosmosOperations for cosmosdb operations + * @param applicationContext for the context + */ public CosmosRepositoryFactory(CosmosOperations cosmosOperations, ApplicationContext applicationContext) { this.cosmosOperations = cosmosOperations; this.applicationContext = applicationContext; @@ -58,7 +66,7 @@ protected Optional getQueryLookupStrategy( private static class CosmosDbQueryLookupStrategy implements QueryLookupStrategy { private final CosmosOperations dbOperations; - public CosmosDbQueryLookupStrategy( + CosmosDbQueryLookupStrategy( CosmosOperations operations, QueryMethodEvaluationContextProvider provider) { this.dbOperations = operations; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java index b1561e6cb3d2..717c9c499b04 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java @@ -5,6 +5,7 @@ import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations; import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -15,7 +16,10 @@ import java.io.Serializable; - +/** + * Adapter for Springs {@link FactoryBean} interface to allow easy setup of cosmos repository factories via Spring + * configuration. + */ public class CosmosRepositoryFactoryBean, S, ID extends Serializable> extends RepositoryFactoryBeanSupport implements ApplicationContextAware { @@ -24,11 +28,20 @@ public class CosmosRepositoryFactoryBean, S, ID exte private CosmosOperations operations; private boolean mappingContextConfigured = false; - + /** + * Creates a new {@link RepositoryFactoryBeanSupport} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ public CosmosRepositoryFactoryBean(Class repositoryInterface) { super(repositoryInterface); } + /** + * Set cosmos operation + * + * @param operations for cosmos operations + */ @Autowired public void setCosmosOperations(CosmosOperations operations) { this.operations = operations; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java index 1904c728de76..7ba254bf0d80 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java @@ -21,11 +21,20 @@ import java.lang.reflect.Method; import java.util.Optional; +/** + * Factory class for reactive cosmos repository contains application context and operations information + */ public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySupport { private final ApplicationContext applicationContext; private final ReactiveCosmosOperations cosmosOperations; + /** + * Initialization + * + * @param cosmosOperations for cosmosdb operations + * @param applicationContext for the context + */ public ReactiveCosmosRepositoryFactory(ReactiveCosmosOperations cosmosOperations, ApplicationContext applicationContext) { this.applicationContext = applicationContext; @@ -61,7 +70,7 @@ protected Optional getQueryLookupStrategy( private static class ReactiveCosmosQueryLookupStrategy implements QueryLookupStrategy { private final ReactiveCosmosOperations cosmosOperations; - public ReactiveCosmosQueryLookupStrategy( + ReactiveCosmosQueryLookupStrategy( ReactiveCosmosOperations operations, QueryMethodEvaluationContextProvider provider) { this.cosmosOperations = operations; } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java index f6057430ab6c..2e23b3f81acd 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java @@ -5,6 +5,7 @@ import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations; import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -15,6 +16,10 @@ import java.io.Serializable; +/** + * Adapter for Springs {@link FactoryBean} interface to allow easy setup of reactive cosmos repository factories + * via Spring configuration. + */ public class ReactiveCosmosRepositoryFactoryBean, S, K extends Serializable> extends RepositoryFactoryBeanSupport @@ -24,10 +29,20 @@ public class ReactiveCosmosRepositoryFactoryBean, S, private ReactiveCosmosOperations cosmosOperations; private boolean mappingContextConfigured = false; + /** + * Creates a new {@link RepositoryFactoryBeanSupport} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ public ReactiveCosmosRepositoryFactoryBean(Class repositoryInterface) { super(repositoryInterface); } + /** + * Set reactive Cosmosdb operations + * + * @param operations contains cosmos operations + */ @Autowired public void setReactiveCosmosOperations(ReactiveCosmosOperations operations) { this.cosmosOperations = operations; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java index c821f87fac86..92689a1e4f8e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java @@ -24,11 +24,20 @@ import java.util.Optional; import java.util.stream.StreamSupport; +/** + * Repository class for simple Cosmos operation + */ public class SimpleCosmosRepository implements CosmosRepository { private final CosmosOperations operation; private final CosmosEntityInformation information; + /** + * Initialization + * + * @param metadata for cosmos entity information + * @param applicationContext to get bean of CosmosOperations class + */ public SimpleCosmosRepository(CosmosEntityInformation metadata, ApplicationContext applicationContext) { this.operation = applicationContext.getBean(CosmosOperations.class); @@ -39,6 +48,12 @@ public SimpleCosmosRepository(CosmosEntityInformation metadata, } } + /** + * Initialization + * + * @param metadata for cosmos entity information + * @param dbOperations for cosmosdb operation + */ public SimpleCosmosRepository(CosmosEntityInformation metadata, CosmosOperations dbOperations) { this.operation = dbOperations; @@ -136,7 +151,8 @@ public List findAllById(Iterable ids) { public Optional findById(ID id) { Assert.notNull(id, "id must not be null"); - if (id instanceof String && !StringUtils.hasText((String) id)) { + if (id instanceof String + && !StringUtils.hasText((String) id)) { return Optional.empty(); } @@ -147,7 +163,8 @@ public Optional findById(ID id) { public Optional findById(ID id, PartitionKey partitionKey) { Assert.notNull(id, "id must not be null"); - if (id instanceof String && !StringUtils.hasText((String) id)) { + if (id instanceof String + && !StringUtils.hasText((String) id)) { return Optional.empty(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java index 3b925c197a94..fa57ae3925cd 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java @@ -20,11 +20,20 @@ import java.io.Serializable; +/** + * Repository class for simple reactive Cosmos operation + */ public class SimpleReactiveCosmosRepository implements ReactiveCosmosRepository { private final CosmosEntityInformation entityInformation; private final ReactiveCosmosOperations cosmosOperations; + /** + * Initialization with metadata and applicationContext will create container if required + * + * @param metadata for entityInformation + * @param applicationContext for cosmosOperations + */ public SimpleReactiveCosmosRepository(CosmosEntityInformation metadata, ApplicationContext applicationContext) { this.cosmosOperations = applicationContext.getBean(ReactiveCosmosOperations.class); @@ -35,6 +44,12 @@ public SimpleReactiveCosmosRepository(CosmosEntityInformation metadata, } } + /** + * Initialization with metadata and reactiveCosmosOperations + * + * @param metadata for entityInformation + * @param reactiveCosmosOperations for cosmosOperations + */ public SimpleReactiveCosmosRepository(CosmosEntityInformation metadata, ReactiveCosmosOperations reactiveCosmosOperations) { this.cosmosOperations = reactiveCosmosOperations; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java new file mode 100644 index 000000000000..55c98f6a55cb --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the support classes of setting up cosmosdb repositories and factories + */ +package com.microsoft.azure.spring.data.cosmosdb.repository.support; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java index c897788b58f4..d93afa8f2b75 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java @@ -8,15 +8,10 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_CONNECTION_STRING; -import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_HOST; -import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_KEY; -import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_INVALID_FAKE_CONNECTION_STRING; -import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.DB_NAME; +import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.*; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @@ -31,14 +26,14 @@ public class CosmosDbFactoryTestIT { @Test(expected = IllegalArgumentException.class) public void testEmptyKey() { - final CosmosDBConfig dbConfig = CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, "", DB_NAME).build(); + final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_HOST, "", DB_NAME).build(); new CosmosDbFactory(dbConfig); } @Test public void testInvalidEndpoint() { final CosmosDBConfig dbConfig = - CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build(); + CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); assertThat(factory).isNotNull(); @@ -47,7 +42,7 @@ public void testInvalidEndpoint() { @Test public void testConnectWithConnectionString() { final CosmosDBConfig dbConfig = - CosmosDBConfig.builder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build(); + CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); assertThat(factory).isNotNull(); @@ -55,13 +50,13 @@ public void testConnectWithConnectionString() { @Test(expected = CosmosDBAccessException.class) public void testInvalidConnectionString() { - CosmosDBConfig.builder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build(); + CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build(); } @Test public void testConnectionPolicyUserAgentKept() { final CosmosDBConfig dbConfig = - CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build(); + CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); factory.getCosmosClient(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java index 3714460b8996..ff87d30ab73b 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java @@ -29,7 +29,7 @@ public class UserAgentTestIT { public void testUserAgentSuffixAppended() { PowerMockito.mockStatic(PropertyLoader.class); Mockito.doReturn(TEST_VERSION).when(PropertyLoader.getProjectVersion()); - final CosmosDBConfig dbConfig = CosmosDBConfig.builder(TestConstants.COSMOSDB_FAKE_HOST, + final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(TestConstants.COSMOSDB_FAKE_HOST, TestConstants.COSMOSDB_FAKE_KEY, TestConstants.DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); factory.getCosmosClient(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java index 6f56a0e75430..0da9f66b63ff 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java @@ -33,7 +33,7 @@ public void setUp() { public void testMemoizedFunctionShouldBeCalledOnlyOnce() { IntStream .range(0, 10) - .forEach(number -> memoizedFunction.apply(KEY)); + .forEach(number -> memoizedFunction.apply(KEY)); assertEquals(1, countMap.get(KEY).get()); } @@ -42,7 +42,7 @@ public void testMemoizedFunctionShouldBeCalledOnlyOnce() { public void testDifferentMemoizersShouldNotShareTheSameCache() { IntStream .range(0, 10) - .forEach(number -> Memoizer.memoize(MemoizerUnitTest::incrCount).apply(KEY)); + .forEach(number -> Memoizer.memoize(MemoizerUnitTest::incrCount).apply(KEY)); assertEquals(10, countMap.get(KEY).get()); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java index d9a39f04818f..5655cbba7a35 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.List; -public class TestConstants { +public final class TestConstants { private static final int SUFFIX_LENGTH = 1; private static final Address ADDRESS_1 = new Address("201107", "Zixing Road", "Shanghai"); @@ -24,10 +24,10 @@ public class TestConstants { public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT; public static final String[] DEFAULT_EXCLUDEDPATHS = {}; public static final String[] DEFAULT_INCLUDEDPATHS = { - "{\"path\":\"/*\",\"indexes\":[" + - "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + - "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}" + - "]}", + "{\"path\":\"/*\",\"indexes\":[" + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":-1}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}" + + "]}", }; public static final String ROLE_COLLECTION_NAME = "RoleCollectionName"; @@ -36,35 +36,35 @@ public class TestConstants { public static final boolean INDEXINGPOLICY_AUTOMATIC = false; public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.LAZY; public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" - + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," - + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," - + "{\"kind\":\"Spatial\",\"dataType\":\"Point\"}" - + "]}"; + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Point\"}" + + "]}"; public static final String INCLUDEDPATH_1 = "{\"path\":\"/cache/*\",\"indexes\":[" - + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":3}," - + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}," - + "{\"kind\":\"Spatial\",\"dataType\":\"LineString\"}" - + "]}"; + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":3}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":3}," + + "{\"kind\":\"Spatial\",\"dataType\":\"LineString\"}" + + "]}"; public static final String INCLUDEDPATH_2 = "{\"path\":\"/entities/*\",\"indexes\":[" - + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":4}," - + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":4}," - + "{\"kind\":\"Spatial\",\"dataType\":\"Polygon\"}" - + "]}"; + + "{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":4}," + + "{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":4}," + + "{\"kind\":\"Spatial\",\"dataType\":\"Polygon\"}" + + "]}"; public static final String[] INCLUDEDPATHS = { - INCLUDEDPATH_0, - INCLUDEDPATH_1, - INCLUDEDPATH_2, + INCLUDEDPATH_0, + INCLUDEDPATH_1, + INCLUDEDPATH_2, }; public static final String EXCLUDEDPATH_0 = "{\"path\":\"/excluded/*\"}"; public static final String EXCLUDEDPATH_1 = "{\"path\":\"/props/*\"}"; public static final String[] EXCLUDEDPATHS = { - EXCLUDEDPATH_0, - EXCLUDEDPATH_1, + EXCLUDEDPATH_0, + EXCLUDEDPATH_1, }; public static final String ORDER_BY_STRING_PATH = "{\"path\":\"/*\",\"indexes\":[" - + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1}," - + "]}"; + + "{\"kind\":\"Range\",\"dataType\":\"String\",\"precision\":-1}," + + "]}"; public static final String STARTSWITH_INCLUDEDPATH = "{\"path\":\"/*\",\"indexes\":[" @@ -73,7 +73,7 @@ public class TestConstants { + "]}"; public static final String[] PERSON_INCLUDEDPATHS = { - STARTSWITH_INCLUDEDPATH + STARTSWITH_INCLUDEDPATH }; public static final String DB_NAME = "testdb"; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java index 16549a191757..eadb92eeecd1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java @@ -19,7 +19,7 @@ public static List toList(Iterable iterable) { } public static void testIndexingPolicyPathsEquals(List policyPaths, - String [] pathsExpected) { + String[] pathsExpected) { if (policyPaths == null) { throw new IllegalStateException("policyPaths should not be null"); } else if (pathsExpected == null) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java index a3fdd33fc4ef..19d6f5237f0f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java @@ -101,7 +101,7 @@ static class TestCosmosConfiguration extends AbstractCosmosConfiguration { @Bean public CosmosDBConfig getConfig() { final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; - return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName).build(); + return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName).build(); } @Override @@ -144,7 +144,7 @@ private RequestOptions getRequestOptions() { public CosmosDBConfig getConfig() { final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; final RequestOptions options = getRequestOptions(); - return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName) + return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName) .requestOptions(options) .build(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java index fee2dfc684d0..289a2e4d33ea 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java @@ -175,7 +175,9 @@ public void testUpsertNewDocument() { cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(), new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON))); - final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString(); + final String firstName = NEW_FIRST_NAME + + "_" + + UUID.randomUUID().toString(); final Person newPerson = new Person(TEST_PERSON.getId(), firstName, NEW_FIRST_NAME, null, null); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java index 28a765c8446b..2094ff7058c0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java @@ -131,15 +131,16 @@ public void testFindByNonExistIdWithPartition() { @Test public void testUpsertNewDocumentPartition() { - final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString(); + final String firstName = NEW_FIRST_NAME + + "_" + UUID.randomUUID().toString(); final PartitionPerson newPerson = new PartitionPerson(TEST_PERSON.getId(), firstName, NEW_LAST_NAME, null, null); final String partitionKeyValue = newPerson.getLastName(); final PartitionPerson partitionPerson = - cosmosTemplate.upsertAndReturnEntity(PartitionPerson.class.getSimpleName(), newPerson - , new PartitionKey(partitionKeyValue)); + cosmosTemplate.upsertAndReturnEntity(PartitionPerson.class.getSimpleName(), newPerson, + new PartitionKey(partitionKeyValue)); final List result = cosmosTemplate.findAll(PartitionPerson.class); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java index 09e796d184ec..bc894d494d8a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java @@ -15,7 +15,7 @@ public class CosmosTemplateUnitTest { @Test(expected = IllegalArgumentException.class) public void rejectNullDbFactory() { - final CosmosDBConfig dbConfig = CosmosDBConfig.builder("", "", TestConstants.DB_NAME).build(); + final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder("", "", TestConstants.DB_NAME).build(); final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); new CosmosTemplate(cosmosDbFactory, null, TestConstants.DB_NAME); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java index 7fbda44c4bb8..3539bc569a90 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java @@ -6,7 +6,6 @@ import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey; import org.springframework.data.annotation.Id; -import java.beans.ConstructorProperties; import java.util.Objects; @Document() @@ -50,9 +49,9 @@ public boolean equals(Object o) { return false; } final Address address = (Address) o; - return Objects.equals(postalCode, address.postalCode) && - Objects.equals(street, address.street) && - Objects.equals(city, address.city); + return Objects.equals(postalCode, address.postalCode) + && Objects.equals(street, address.street) + && Objects.equals(city, address.city); } @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java index 73fab9000764..3c2bfc9c5dd4 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java @@ -37,11 +37,15 @@ public void setTitle(String title) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Contact contact = (Contact) o; - return Objects.equals(logicId, contact.logicId) && - Objects.equals(title, contact.title); + return Objects.equals(logicId, contact.logicId) + && Objects.equals(title, contact.title); } @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java index c0a70b24e80b..872e92b2dd0f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java @@ -52,12 +52,16 @@ public void setDepartment(String department) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Course course = (Course) o; - return courseId.equals(course.courseId) && - name.equals(course.name) && - department.equals(course.department); + return courseId.equals(course.courseId) + && name.equals(course.name) + && department.equals(course.department); } @Override diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java index 738e2022acc8..e79d5a49b696 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java @@ -47,12 +47,16 @@ public void setUser(User user) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Customer customer = (Customer) o; - return Objects.equals(id, customer.id) && - Objects.equals(level, customer.level) && - Objects.equals(user, customer.user); + return Objects.equals(id, customer.id) + && Objects.equals(level, customer.level) + && Objects.equals(user, customer.user); } @Override @@ -62,11 +66,15 @@ public int hashCode() { @Override public String toString() { - return "Customer{" + - "id='" + id + '\'' + - ", level=" + level + - ", user=" + user + - '}'; + return "Customer{" + + "id='" + + id + + '\'' + + ", level=" + + level + + ", user=" + + user + + '}'; } public static class User { @@ -98,11 +106,15 @@ public void setAge(Long age) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } User user = (User) o; - return Objects.equals(name, user.name) && - Objects.equals(age, user.age); + return Objects.equals(name, user.name) + && Objects.equals(age, user.age); } @Override @@ -112,10 +124,13 @@ public int hashCode() { @Override public String toString() { - return "User{" + - "name='" + name + '\'' + - ", age=" + age + - '}'; + return "User{" + + "name='" + + name + + '\'' + + ", age=" + + age + + '}'; } } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java index b817b7427849..0dc90ea96a1d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java @@ -41,11 +41,15 @@ public void setName(String name) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } IntegerIdDomain that = (IntegerIdDomain) o; - return Objects.equals(number, that.number) && - Objects.equals(name, that.name); + return Objects.equals(number, that.number) + && Objects.equals(name, that.name); } @Override @@ -55,9 +59,12 @@ public int hashCode() { @Override public String toString() { - return "IntegerIdDomain{" + - "number=" + number + - ", name='" + name + '\'' + - '}'; + return "IntegerIdDomain{" + + "number=" + + number + + ", name='" + + name + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java index 91a3dc273645..998b03810ef3 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java @@ -61,13 +61,17 @@ public void setImportance(Importance importance) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Memo memo = (Memo) o; - return Objects.equals(id, memo.id) && - Objects.equals(message, memo.message) && - Objects.equals(date, memo.date) && - importance == memo.importance; + return Objects.equals(id, memo.id) + && Objects.equals(message, memo.message) + && Objects.equals(date, memo.date) + && importance == memo.importance; } @Override @@ -77,12 +81,18 @@ public int hashCode() { @Override public String toString() { - return "Memo{" + - "id='" + id + '\'' + - ", message='" + message + '\'' + - ", date=" + date + - ", importance=" + importance + - '}'; + return "Memo{" + + "id='" + + id + + '\'' + + ", message='" + + message + + '\'' + + ", date=" + + date + + ", importance=" + + importance + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java index f3d43f782f62..ef76b39d97c2 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java @@ -64,14 +64,18 @@ public void setShippingAddresses(List
shippingAddresses) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } NoDBAnnotationPerson that = (NoDBAnnotationPerson) o; - return Objects.equals(id, that.id) && - Objects.equals(firstName, that.firstName) && - Objects.equals(lastName, that.lastName) && - Objects.equals(hobbies, that.hobbies) && - Objects.equals(shippingAddresses, that.shippingAddresses); + return Objects.equals(id, that.id) + && Objects.equals(firstName, that.firstName) + && Objects.equals(lastName, that.lastName) + && Objects.equals(hobbies, that.hobbies) + && Objects.equals(shippingAddresses, that.shippingAddresses); } @Override @@ -81,12 +85,20 @@ public int hashCode() { @Override public String toString() { - return "NoDBAnnotationPerson{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - ", hobbies=" + hobbies + - ", shippingAddresses=" + shippingAddresses + - '}'; + return "NoDBAnnotationPerson{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + ", hobbies=" + + hobbies + + ", shippingAddresses=" + + shippingAddresses + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java index f8bf72d0bd15..947b30baf43c 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java @@ -25,9 +25,9 @@ public boolean equals(Object o) { return false; } final PageableAddress address = (PageableAddress) o; - return Objects.equals(postalCode, address.postalCode) && - Objects.equals(street, address.street) && - Objects.equals(city, address.city); + return Objects.equals(postalCode, address.postalCode) + && Objects.equals(street, address.street) + && Objects.equals(city, address.city); } @Override @@ -67,10 +67,16 @@ public void setCity(String city) { @Override public String toString() { - return "PageableAddress{" + - "postalCode='" + postalCode + '\'' + - ", street='" + street + '\'' + - ", city='" + city + '\'' + - '}'; + return "PageableAddress{" + + "postalCode='" + + postalCode + + '\'' + + ", street='" + + street + + '\'' + + ", city='" + + city + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java index c0c2fb1afe54..5796f18e8af7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java @@ -58,13 +58,17 @@ public void setImportance(Importance importance) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PageableMemo that = (PageableMemo) o; - return Objects.equals(id, that.id) && - Objects.equals(message, that.message) && - Objects.equals(date, that.date) && - importance == that.importance; + return Objects.equals(id, that.id) + && Objects.equals(message, that.message) + && Objects.equals(date, that.date) + && importance == that.importance; } @Override @@ -74,11 +78,17 @@ public int hashCode() { @Override public String toString() { - return "PageableMemo{" + - "id='" + id + '\'' + - ", message='" + message + '\'' + - ", date=" + date + - ", importance=" + importance + - '}'; + return "PageableMemo{" + + "id='" + + id + + '\'' + + ", message='" + + message + + '\'' + + ", date=" + + date + + ", importance=" + + importance + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java index b1c3a109e2f0..44ac9016bbf9 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java @@ -87,14 +87,18 @@ public void set_etag(String _etag) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PageablePerson that = (PageablePerson) o; - return Objects.equals(id, that.id) && - Objects.equals(firstName, that.firstName) && - Objects.equals(lastName, that.lastName) && - Objects.equals(hobbies, that.hobbies) && - Objects.equals(shippingAddresses, that.shippingAddresses); + return Objects.equals(id, that.id) + && Objects.equals(firstName, that.firstName) + && Objects.equals(lastName, that.lastName) + && Objects.equals(hobbies, that.hobbies) + && Objects.equals(shippingAddresses, that.shippingAddresses); } @Override @@ -104,13 +108,23 @@ public int hashCode() { @Override public String toString() { - return "PageablePerson{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - ", hobbies=" + hobbies + - ", shippingAddresses=" + shippingAddresses + - ", _etag='" + _etag + '\'' + - '}'; + return "PageablePerson{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + ", hobbies=" + + hobbies + + ", shippingAddresses=" + + shippingAddresses + + ", _etag='" + + _etag + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java index 987b9fb487b1..fefe9b080a9d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java @@ -72,14 +72,18 @@ public void setShippingAddresses(List
shippingAddresses) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PartitionPerson that = (PartitionPerson) o; - return Objects.equals(id, that.id) && - Objects.equals(firstName, that.firstName) && - Objects.equals(lastName, that.lastName) && - Objects.equals(hobbies, that.hobbies) && - Objects.equals(shippingAddresses, that.shippingAddresses); + return Objects.equals(id, that.id) + && Objects.equals(firstName, that.firstName) + && Objects.equals(lastName, that.lastName) + && Objects.equals(hobbies, that.hobbies) + && Objects.equals(shippingAddresses, that.shippingAddresses); } @Override @@ -89,12 +93,20 @@ public int hashCode() { @Override public String toString() { - return "PartitionPerson{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - ", hobbies=" + hobbies + - ", shippingAddresses=" + shippingAddresses + - '}'; + return "PartitionPerson{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + ", hobbies=" + + hobbies + + ", shippingAddresses=" + + shippingAddresses + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java index bef11d622e6f..8038c1826df0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java @@ -87,14 +87,18 @@ public void set_etag(String _etag) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Person person = (Person) o; - return Objects.equals(id, person.id) && - Objects.equals(firstName, person.firstName) && - Objects.equals(lastName, person.lastName) && - Objects.equals(hobbies, person.hobbies) && - Objects.equals(shippingAddresses, person.shippingAddresses); + return Objects.equals(id, person.id) + && Objects.equals(firstName, person.firstName) + && Objects.equals(lastName, person.lastName) + && Objects.equals(hobbies, person.hobbies) + && Objects.equals(shippingAddresses, person.shippingAddresses); } @Override @@ -104,13 +108,23 @@ public int hashCode() { @Override public String toString() { - return "Person{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - ", hobbies=" + hobbies + - ", shippingAddresses=" + shippingAddresses + - ", _etag='" + _etag + '\'' + - '}'; + return "Person{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + ", hobbies=" + + hobbies + + ", shippingAddresses=" + + shippingAddresses + + ", _etag='" + + _etag + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java index 38137e123cea..436b040198fa 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java @@ -87,15 +87,19 @@ public void setForkCount(Long forkCount) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Project project = (Project) o; - return Objects.equals(id, project.id) && - Objects.equals(name, project.name) && - Objects.equals(creator, project.creator) && - Objects.equals(hasReleased, project.hasReleased) && - Objects.equals(starCount, project.starCount) && - Objects.equals(forkCount, project.forkCount); + return Objects.equals(id, project.id) + && Objects.equals(name, project.name) + && Objects.equals(creator, project.creator) + && Objects.equals(hasReleased, project.hasReleased) + && Objects.equals(starCount, project.starCount) + && Objects.equals(forkCount, project.forkCount); } @Override @@ -105,13 +109,22 @@ public int hashCode() { @Override public String toString() { - return "Project{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", creator='" + creator + '\'' + - ", hasReleased=" + hasReleased + - ", starCount=" + starCount + - ", forkCount=" + forkCount + - '}'; + return "Project{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", creator='" + + creator + + '\'' + + ", hasReleased=" + + hasReleased + + ", starCount=" + + starCount + + ", forkCount=" + + forkCount + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java index 5afb3c615f04..541b32fab8f0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java @@ -47,11 +47,15 @@ public void setUrl(String url) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Question question = (Question) o; - return Objects.equals(id, question.id) && - Objects.equals(url, question.url); + return Objects.equals(id, question.id) + && Objects.equals(url, question.url); } @Override @@ -61,9 +65,13 @@ public int hashCode() { @Override public String toString() { - return "Question{" + - "id='" + id + '\'' + - ", url='" + url + '\'' + - '}'; + return "Question{" + + "id='" + + id + + '\'' + + ", url='" + + url + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java index 5dd3f7ace423..6bc7ca4233d0 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java @@ -66,12 +66,16 @@ public void setLevel(String level) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Role role = (Role) o; - return Objects.equals(id, role.id) && - Objects.equals(name, role.name) && - Objects.equals(level, role.level); + return Objects.equals(id, role.id) + && Objects.equals(name, role.name) + && Objects.equals(level, role.level); } @Override @@ -81,11 +85,17 @@ public int hashCode() { @Override public String toString() { - return "Role{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", level='" + level + '\'' + - '}'; + return "Role{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", level='" + + level + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java index 2b267337818a..38437509175d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java @@ -87,15 +87,19 @@ public void setForkCount(Long forkCount) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } SortedProject that = (SortedProject) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name) && - Objects.equals(creator, that.creator) && - Objects.equals(hasReleased, that.hasReleased) && - Objects.equals(starCount, that.starCount) && - Objects.equals(forkCount, that.forkCount); + return Objects.equals(id, that.id) + && Objects.equals(name, that.name) + && Objects.equals(creator, that.creator) + && Objects.equals(hasReleased, that.hasReleased) + && Objects.equals(starCount, that.starCount) + && Objects.equals(forkCount, that.forkCount); } @Override @@ -105,13 +109,22 @@ public int hashCode() { @Override public String toString() { - return "SortedProject{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", creator='" + creator + '\'' + - ", hasReleased=" + hasReleased + - ", starCount=" + starCount + - ", forkCount=" + forkCount + - '}'; + return "SortedProject{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", creator='" + + creator + + '\'' + + ", hasReleased=" + + hasReleased + + ", starCount=" + + starCount + + ", forkCount=" + + forkCount + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java index 97d31e1d066a..eb698245156f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java @@ -48,12 +48,16 @@ public void setLastName(String lastName) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } SpELBeanStudent that = (SpELBeanStudent) o; - return Objects.equals(id, that.id) && - Objects.equals(firstName, that.firstName) && - Objects.equals(lastName, that.lastName); + return Objects.equals(id, that.id) + && Objects.equals(firstName, that.firstName) + && Objects.equals(lastName, that.lastName); } @Override @@ -63,10 +67,16 @@ public int hashCode() { @Override public String toString() { - return "SpELBeanStudent{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - '}'; + return "SpELBeanStudent{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java index 88c9e6cf40d7..83daf0e542d2 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java @@ -48,12 +48,16 @@ public void setLastName(String lastName) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } SpELPropertyStudent that = (SpELPropertyStudent) o; - return Objects.equals(id, that.id) && - Objects.equals(firstName, that.firstName) && - Objects.equals(lastName, that.lastName); + return Objects.equals(id, that.id) + && Objects.equals(firstName, that.firstName) + && Objects.equals(lastName, that.lastName); } @Override @@ -63,10 +67,16 @@ public int hashCode() { @Override public String toString() { - return "SpELPropertyStudent{" + - "id='" + id + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - '}'; + return "SpELPropertyStudent{" + + "id='" + + id + + '\'' + + ", firstName='" + + firstName + + '\'' + + ", lastName='" + + lastName + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java index adf4e4dadf65..5166e51fb51f 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java @@ -17,8 +17,12 @@ public void setArea(int area) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Shape shape = (Shape) o; return area == shape.area; } @@ -30,7 +34,10 @@ public int hashCode() { @Override public String toString() { - return "Shape{" + "area=" + area + '}'; + return "Shape{" + + "area=" + + area + + '}'; } public Shape(int area) { diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java index 2574d0a4bea0..e82e168f8fc6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java @@ -39,12 +39,18 @@ public void setLength(int length) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } Square square = (Square) o; - return length == square.length && - Objects.equals(id, square.id); + return length == square.length + && Objects.equals(id, square.id); } @Override @@ -54,6 +60,12 @@ public int hashCode() { @Override public String toString() { - return "Square{" + "id='" + id + '\'' + ", length=" + length + '}'; + return "Square{" + + "id='" + + id + + '\'' + + ", length=" + + length + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java index d893bbc89282..04cc2a353779 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java @@ -23,6 +23,6 @@ public class PerfConfiguration extends AbstractCosmosConfiguration { @Bean public CosmosDBConfig getConfig() { - return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build(); + return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build(); } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java index 0209ef5deef7..f992d5b16117 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java @@ -34,7 +34,7 @@ class PerfItem { private int times; private float diffToSdk; - public PerfItem(OperationType type, long springCost, long sdkCost, int times) { + PerfItem(OperationType type, long springCost, long sdkCost, int times) { this.type = type; this.springCost = springCost; this.sdkCost = sdkCost; @@ -84,14 +84,18 @@ public void setDiffToSdk(float diffToSdk) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PerfItem perfItem = (PerfItem) o; - return springCost == perfItem.springCost && - sdkCost == perfItem.sdkCost && - times == perfItem.times && - Float.compare(perfItem.diffToSdk, diffToSdk) == 0 && - type == perfItem.type; + return springCost == perfItem.springCost + && sdkCost == perfItem.sdkCost + && times == perfItem.times + && Float.compare(perfItem.diffToSdk, diffToSdk) == 0 + && type == perfItem.type; } @Override @@ -101,8 +105,18 @@ public int hashCode() { @Override public String toString() { - return "[type=" + type.toString() + ", springCost=" + springCost + ", sdkCost=" + sdkCost + ", times=" + - times + ", diffToSdk=" + (diffToSdk * 100 + "%") + "];"; + return "[type=" + + type.toString() + + ", springCost=" + + springCost + + ", sdkCost=" + + sdkCost + + ", times=" + + times + + ", diffToSdk=" + + (diffToSdk * 100 + + "%") + + "];"; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java index 2f8c5b0d83ec..4be9232067b5 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java @@ -39,11 +39,15 @@ public void setName(String name) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PerfPerson that = (PerfPerson) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name); + return Objects.equals(id, that.id) + && Objects.equals(name, that.name); } @Override @@ -53,9 +57,13 @@ public int hashCode() { @Override public String toString() { - return "PerfPerson{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - '}'; + return "PerfPerson{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + '}'; } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java index bc18a1831630..bf5462d42c1a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java @@ -79,8 +79,13 @@ public CosmosItemProperties findById(String id) { final Iterator> feedResponseIterator = cosmosSyncClient.getDatabase(dbName) .getContainer(containerName) - .queryItems("SELECT * FROM " + containerName + " WHERE " + - containerName + ".id='" + id + "'", new FeedOptions()); + .queryItems("SELECT * FROM " + + containerName + + " WHERE " + + containerName + + ".id='" + + id + + "'", new FeedOptions()); CosmosItemProperties itemProperties = null; if (feedResponseIterator.hasNext()) { final List results = feedResponseIterator.next().results(); @@ -193,7 +198,8 @@ private List searchBySize(int size, FeedOptions options) { final Iterator it = getCosmosItemPropertiesList(sql).iterator(); final List entities = new ArrayList<>(); int i = 0; - while (it.hasNext() && i++ < size) { + while (it.hasNext() + && i++ < size) { // This convert here is in order to mock data conversion in real use case, in order to compare with // Spring Data mapping final CosmosItemProperties d = it.next(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java index 6612ff254070..061e6a97e4d5 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java @@ -28,7 +28,7 @@ public static void createDatabase(CosmosSyncClient documentClient, String databa } public static void deleteContainer(CosmosSyncClient documentClient, String databaseName, String containerName) - throws CosmosClientException{ + throws CosmosClientException { final RequestOptions requestOptions = new RequestOptions(); requestOptions.setOfferThroughput(1000); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java index 573ad516fad1..6b10fb9e4172 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java @@ -58,10 +58,11 @@ public CosmosDBConfig getConfig() { final RequestOptions options = getRequestOptions(); final CosmosDBConfig.CosmosDBConfigBuilder builder; - if (StringUtils.hasText(this.cosmosDbUri) && StringUtils.hasText(this.cosmosDbKey)) { - builder = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName); + if (StringUtils.hasText(this.cosmosDbUri) + && StringUtils.hasText(this.cosmosDbKey)) { + builder = CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName); } else { - builder = CosmosDBConfig.builder(connectionString, dbName); + builder = CosmosDBConfig.cosmosDBConfigbuilder(connectionString, dbName); } return builder.requestOptions(options) .populateQueryMetrics(populateQueryMetrics) diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java index 3638f31c8b90..67573dd759f6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java @@ -215,7 +215,7 @@ private static class InvalidDomain { private String location; - public InvalidDomain(int count, String location) { + InvalidDomain(int count, String location) { this.count = count; this.location = location; } @@ -238,11 +238,15 @@ public void setLocation(String location) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } InvalidDomain that = (InvalidDomain) o; - return count == that.count && - Objects.equals(location, that.location); + return count == that.count + && Objects.equals(location, that.location); } @Override @@ -252,10 +256,13 @@ public int hashCode() { @Override public String toString() { - return "InvalidDomain{" + - "count=" + count + - ", location='" + location + '\'' + - '}'; + return "InvalidDomain{" + + "count=" + + count + + ", location='" + + location + + '\'' + + '}'; } } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java index 16012a8e3a1d..d97f910d6b4a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java @@ -83,27 +83,27 @@ public void testDynamicContainerNameWithBeanExpression() { @Test public void testDatabaseOperationsOnDynamicallyNamedCollection() throws ClassNotFoundException { - final CosmosDBConfig dbConfig = CosmosDBConfig.builder(dbUri, dbKey, TestConstants.DB_NAME).build(); - final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); + final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(dbUri, dbKey, TestConstants.DB_NAME).build(); + final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); - cosmosEntityInformation = new CosmosEntityInformation<>(SpELPropertyStudent.class); - final CosmosMappingContext dbContext = new CosmosMappingContext(); - dbContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); + cosmosEntityInformation = new CosmosEntityInformation<>(SpELPropertyStudent.class); + final CosmosMappingContext dbContext = new CosmosMappingContext(); + dbContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class)); - final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); - final MappingCosmosConverter mappingConverter = new MappingCosmosConverter(dbContext, objectMapper); - staticTemplate = new CosmosTemplate(dbFactory, mappingConverter, TestConstants.DB_NAME); + final ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + final MappingCosmosConverter mappingConverter = new MappingCosmosConverter(dbContext, objectMapper); + staticTemplate = new CosmosTemplate(dbFactory, mappingConverter, TestConstants.DB_NAME); - staticTemplate.createContainerIfNotExists(cosmosEntityInformation); + staticTemplate.createContainerIfNotExists(cosmosEntityInformation); - final SpELPropertyStudent insertedRecord = + final SpELPropertyStudent insertedRecord = staticTemplate.insert(cosmosEntityInformation.getContainerName(), TEST_PROPERTY_STUDENT, null); - assertNotNull(insertedRecord); + assertNotNull(insertedRecord); - final SpELPropertyStudent readRecord = + final SpELPropertyStudent readRecord = staticTemplate.findById(TestConstants.DYNAMIC_PROPERTY_COLLECTION_NAME, insertedRecord.getId(), SpELPropertyStudent.class); - assertNotNull(readRecord); + assertNotNull(readRecord); } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java index a2e864969afc..76d794a6eda1 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository; @Repository -public interface PageableAddressRepository extends PagingAndSortingRepository{ +public interface PageableAddressRepository extends PagingAndSortingRepository { Page findByStreet(String street, Pageable pageable); Page findByCity(String city, Pageable pageable); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java index cf6f65928c96..598f0359d8c7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java @@ -184,7 +184,7 @@ private static class VersionedVolunteer { @Version private String _etag; - public VersionedVolunteer() { + VersionedVolunteer() { } public String getId() { @@ -213,12 +213,16 @@ public void set_etag(String _etag) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } VersionedVolunteer that = (VersionedVolunteer) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name) && - Objects.equals(_etag, that._etag); + return Objects.equals(id, that.id) + && Objects.equals(name, that.name) + && Objects.equals(_etag, that._etag); } @Override @@ -228,11 +232,17 @@ public int hashCode() { @Override public String toString() { - return "VersionedVolunteer{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", _etag='" + _etag + '\'' + - '}'; + return "VersionedVolunteer{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", _etag='" + + _etag + + '\'' + + '}'; } } @@ -242,7 +252,7 @@ private static class WrongVersionType { private String name; private long _etag; - public WrongVersionType() { + WrongVersionType() { } public String getId() { @@ -271,12 +281,16 @@ public void set_etag(long _etag) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } WrongVersionType that = (WrongVersionType) o; - return _etag == that._etag && - Objects.equals(id, that.id) && - Objects.equals(name, that.name); + return _etag == that._etag + && Objects.equals(id, that.id) + && Objects.equals(name, that.name); } @Override @@ -286,11 +300,16 @@ public int hashCode() { @Override public String toString() { - return "WrongVersionType{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", _etag=" + _etag + - '}'; + return "WrongVersionType{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", _etag=" + + _etag + + '}'; } } @@ -301,7 +320,7 @@ private static class VersionOnWrongField { private String name; private String _etag; - public VersionOnWrongField() { + VersionOnWrongField() { } public String getId() { @@ -330,12 +349,16 @@ public void set_etag(String _etag) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } VersionOnWrongField that = (VersionOnWrongField) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name) && - Objects.equals(_etag, that._etag); + return Objects.equals(id, that.id) + && Objects.equals(name, that.name) + && Objects.equals(_etag, that._etag); } @Override @@ -345,11 +368,17 @@ public int hashCode() { @Override public String toString() { - return "VersionOnWrongField{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", _etag='" + _etag + '\'' + - '}'; + return "VersionOnWrongField{" + + "id='" + + id + + '\'' + + ", name='" + + name + + '\'' + + ", _etag='" + + _etag + + '\'' + + '}'; } } } From d1e7aafc24ea003c93a956020587de9822be1826 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Wed, 17 Jun 2020 17:25:14 +0800 Subject: [PATCH 07/17] update underlying library versions --- .../checkstyle/checkstyle-suppressions.xml | 8 ++--- eng/versioning/external_dependencies.txt | 8 +---- .../pom.xml | 31 +------------------ ...ppRoleStatelessAuthenticationFilterIT.java | 14 ++++----- sdk/spring/azure-spring-boot/pom.xml | 4 +-- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 29 +++++++++-------- .../config/CosmosDBConfig.java | 10 +++--- .../core/CosmosTemplate.java | 2 +- .../core/ReactiveCosmosTemplate.java | 2 +- .../core/convert/MappingCosmosConverter.java | 2 +- .../core/query/CosmosPageImpl.java | 2 +- .../core/query/CosmosPageRequest.java | 2 +- .../support/CosmosEntityInformation.java | 14 ++++----- .../CosmosDbFactoryTestIT.java | 10 +++--- .../UserAgentTestIT.java | 2 +- .../config/AbstractCosmosConfigurationIT.java | 4 +-- .../core/CosmosTemplateUnitTest.java | 2 +- .../performance/PerfConfiguration.java | 2 +- .../repository/TestRepositoryConfig.java | 4 +-- .../integration/SpELCosmosDBAnnotationIT.java | 2 +- 20 files changed, 57 insertions(+), 97 deletions(-) diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml index 36a491991c0a..143fd1dc5216 100755 --- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -460,11 +460,7 @@ - - - + files="com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest.java"/> @@ -474,7 +470,7 @@ - + diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index bf6440512b57..541816968166 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -22,7 +22,7 @@ com.microsoft.azure:azure-keyvault-cryptography;1.2.2 com.microsoft.azure:azure-media;0.9.8 com.microsoft.azure:azure-servicebus-jms;0.0.2 com.microsoft.azure:qpid-proton-j-extensions;1.2.3 -com.microsoft.azure:spring-data-cosmosdb;2.2.3.FIX1 +com.microsoft.azure:spotbugs-maven-plugin;1.2.1 com.microsoft.rest:client-runtime;1.7.4 com.microsoft.rest.v2:client-runtime;2.1.1 com.microsoft.spring.data.gremlin:spring-data-gremlin;2.2.3 @@ -271,11 +271,5 @@ spring_com.microsoft.azure:azure;1.34.0 #sdk\spring\spring-data-cosmosdb\pom.xml spring_org.springframework:spring-web;5.2.6.RELEASE spring_com.microsoft.azure:azure-cosmos;3.7.3 -spring_com.fasterxml.jackson.datatype:jackson-datatype-jsr310;2.10.0 -#spring_org.mockito:mockito-core;2.8.9 -#spring_org.powermock:powermock-module-junit4;1.7.1 -spring_org.powermock:powermock-api-mockito2;1.7.1 spring_org.springframework.boot:spring-boot-starter-test;2.3.0.RELEASE -spring_io.projectreactor:reactor-test;3.3.0.RELEASE -spring_com.google.code.gson:gson;2.8.4 diff --git a/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml b/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml index 3ae872757e87..096a0b2cc56f 100644 --- a/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml +++ b/sdk/spring/azure-spring-boot-starter-keyvault-secrets/pom.xml @@ -42,35 +42,6 @@ org.apache.maven.plugins maven-enforcer-plugin 3.0.0-M3 - - - enforce-environment-variable-is-set - - enforce - - - - - AZURE_TENANT - Set the AZURE_TENANT environment variable to your Azure Tenant ID - - - AZURE_SUBSCRIPTION - Set the AZURE_SUBSCRIPTION environment variable to your Azure Subscription ID - - - AZURE_CLIENT_ID - Set the AZURE_CLIENT_ID environment variable to your Application (Client) ID - - - AZURE_CLIENT_SECRET - Set the AZURE_CLIENT_SECRET environment variable to your Application (Client) Secret - - - true - - - @@ -208,7 +179,7 @@ - + diff --git a/sdk/spring/azure-spring-boot-tests/azure-spring-boot-test-aad/src/test/java/com/microsoft/azure/test/aad/approle/AADAppRoleStatelessAuthenticationFilterIT.java b/sdk/spring/azure-spring-boot-tests/azure-spring-boot-test-aad/src/test/java/com/microsoft/azure/test/aad/approle/AADAppRoleStatelessAuthenticationFilterIT.java index 8b4002486a27..504e9eac4633 100644 --- a/sdk/spring/azure-spring-boot-tests/azure-spring-boot-test-aad/src/test/java/com/microsoft/azure/test/aad/approle/AADAppRoleStatelessAuthenticationFilterIT.java +++ b/sdk/spring/azure-spring-boot-tests/azure-spring-boot-test-aad/src/test/java/com/microsoft/azure/test/aad/approle/AADAppRoleStatelessAuthenticationFilterIT.java @@ -45,7 +45,7 @@ public class AADAppRoleStatelessAuthenticationFilterIT { @Test public void testAADAppRoleStatelessAuthenticationFilter() { final OAuthResponse authResponse = OAuthUtils.executeOAuth2ROPCFlow(System.getenv(AAD_CLIENT_ID), - System.getenv(AAD_CLIENT_SECRET)); + System.getenv(AAD_CLIENT_SECRET)); assertNotNull(authResponse); try (AppRunner app = new AppRunner(DumbApp.class)) { @@ -56,13 +56,13 @@ public void testAADAppRoleStatelessAuthenticationFilter() { app.start(); final ResponseEntity response = restTemplate.exchange(app.root() + "public", - HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class, new HashMap<>()); + HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class, new HashMap<>()); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals("public endpoint response", response.getBody()); try { restTemplate.exchange(app.root() + "authorized", - HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class, new HashMap<>()); + HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class, new HashMap<>()); } catch (Exception e) { assertEquals(HttpClientErrorException.Forbidden.class, e.getClass()); } @@ -72,7 +72,7 @@ public void testAADAppRoleStatelessAuthenticationFilter() { final HttpEntity entity = new HttpEntity<>(headers); final ResponseEntity response2 = restTemplate.exchange(app.root() + "authorized", - HttpMethod.GET, entity, String.class, new HashMap<>()); + HttpMethod.GET, entity, String.class, new HashMap<>()); assertEquals(HttpStatus.OK, response2.getStatusCode()); assertEquals("authorized endpoint response", response2.getBody()); @@ -102,9 +102,9 @@ protected void configure(HttpSecurity http) throws Exception { http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER); http.authorizeRequests() - .antMatchers("/admin/**").hasRole("Admin") - .antMatchers("/", "/index.html", "/public").permitAll() - .anyRequest().authenticated(); + .antMatchers("/admin/**").hasRole("Admin") + .antMatchers("/", "/index.html", "/public").permitAll() + .anyRequest().authenticated(); http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class); } diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index 663489604b9b..353c7c2c9cd1 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -116,7 +116,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.2.3.FIX1 + 2.3.1-beta.1 true @@ -274,7 +274,7 @@ net.minidev:json-smart:[2.3] com.microsoft.azure:azure-servicebus-jms:[0.0.2] com.microsoft.azure:msal4j:[1.3.0] - com.microsoft.azure:spring-data-cosmosdb:[2.2.3.FIX1] + com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] com.microsoft.spring.data.gremlin:spring-data-gremlin:[2.2.3] com.nimbusds:nimbus-jose-jwt:[7.9] io.micrometer:micrometer-core:[1.3.0] diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 4cd0da038687..4fd17b2aa20c 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -12,7 +12,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.3.1-SNAPSHOT + 2.3.1-beta.1 Spring Data for Azure Cosmos DB SQL API Spring Data for Azure Cosmos DB SQL API @@ -95,7 +95,7 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.10.0 + 2.10.1 org.json @@ -113,19 +113,19 @@ org.mockito mockito-core - 2.8.9 + 3.0.0 test org.powermock powermock-module-junit4 - 1.7.1 + 2.0.2 test org.powermock powermock-api-mockito2 - 1.7.1 + 2.0.2 test @@ -144,7 +144,7 @@ io.projectreactor reactor-test - 3.3.0.RELEASE + 3.3.5.RELEASE test @@ -158,7 +158,7 @@ com.google.code.gson gson - 2.8.4 + 2.8.5 test @@ -183,14 +183,13 @@ - org.springframework:*:5.2.6.RELEASE - org.springframework.data:spring-data-commons:2.3.0.RELEASE - com.microsoft.azure:azure-cosmos:3.7.3 - org.javatuples:javatuples:1.2 - com.fasterxml.jackson.datatype:*:2.10.0 - org.json:json:20140107 - com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 - com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + org.springframework:*:5.2.6.RELEASE + org.springframework.data:spring-data-commons:2.3.0.RELEASE + com.microsoft.azure:azure-cosmos:3.7.3 + org.javatuples:javatuples:1.2 + com.fasterxml.jackson.datatype:*:2.10.0 + org.json:json:20140107 + com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 org.slf4j:slf4j-simple:[1.7.25] diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java index 386e959119ab..d8b607986dd7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java @@ -171,8 +171,8 @@ public void setPopulateQueryMetrics(boolean populateQueryMetrics) { * @param database must not be {@literal null} * @return CosmosDBConfigBuilder */ - public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, CosmosKeyCredential cosmosKeyCredential, - String database) { + public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential, + String database) { return defaultBuilder() .uri(uri) .cosmosKeyCredential(cosmosKeyCredential) @@ -189,7 +189,7 @@ public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, CosmosKeyC * @param database must not be {@literal null} * @return CosmosDBConfigBuilder */ - public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, String key, String database) { + public static CosmosDBConfigBuilder builder(String uri, String key, String database) { return defaultBuilder() .uri(uri) .key(key) @@ -206,12 +206,12 @@ public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String uri, String key * @return CosmosDBConfigBuilder * @throws CosmosDBAccessException for invalid connection string */ - public static CosmosDBConfigBuilder cosmosDBConfigbuilder(String connectionString, String database) { + public static CosmosDBConfigBuilder builder(String connectionString, String database) { Assert.hasText(connectionString, "connection string should have text!"); try { final String uri = connectionString.split(";")[0].split("=")[1]; final String key = connectionString.split(";")[1].split("=")[1]; - return cosmosDBConfigbuilder(uri, key, database); + return builder(uri, key, database); } catch (ArrayIndexOutOfBoundsException e) { throw new CosmosDBAccessException("could not parse connection string"); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java index bc45fd3af611..2e3a5c116cb7 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java @@ -65,7 +65,7 @@ public class CosmosTemplate implements CosmosOperations, ApplicationContextAware private final boolean isPopulateQueryMetrics; private final CosmosClient cosmosClient; - private Function, CosmosEntityInformation> entityInfoCreator = + private final Function, CosmosEntityInformation> entityInfoCreator = Memoizer.memoize(this::getCosmosEntityInformation); /** diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java index 07a6e861c397..38200f453b31 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java @@ -55,7 +55,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica private final ResponseDiagnosticsProcessor responseDiagnosticsProcessor; private final boolean isPopulateQueryMetrics; - private Function, CosmosEntityInformation> entityInfoCreator = + private final Function, CosmosEntityInformation> entityInfoCreator = Memoizer.memoize(this::getCosmosEntityInformation); private final List containerNameCache; diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java index bb409059c338..a09e3f8e4de5 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java @@ -42,7 +42,7 @@ public class MappingCosmosConverter CosmosPersistentProperty> mappingContext; protected GenericConversionService conversionService; private ApplicationContext applicationContext; - private ObjectMapper objectMapper; + private final ObjectMapper objectMapper; /** * Initialization diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java index 2c0910740750..771e53910e51 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java @@ -20,7 +20,7 @@ public class CosmosPageImpl extends PageImpl { // For any query, CosmosDB returns documents less than or equal to page size // Depending on the number of RUs, the number of returned documents can change // Storing the offset of current page, helps to check hasNext and next values - private long offset; + private final long offset; /** * Constructor of {@code CosmosPageImpl}. diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java index 9bb916889105..68d98dea0c30 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java @@ -20,7 +20,7 @@ public class CosmosPageRequest extends PageRequest { private long offset; // Request continuation token used to resume query - private String requestContinuation; + private final String requestContinuation; /** * Creates a new {@link PageRequest} with unsorted parameters applied. diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java index 5693c99bda2c..14dd833c76bc 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java @@ -32,13 +32,13 @@ public class CosmosEntityInformation extends AbstractEntityInformation { private static final String ETAG = "_etag"; - private Field id; - private Field partitionKeyField; - private String containerName; - private Integer requestUnit; - private Integer timeToLive; - private IndexingPolicy indexingPolicy; - private boolean isVersioned; + private final Field id; + private final Field partitionKeyField; + private final String containerName; + private final Integer requestUnit; + private final Integer timeToLive; + private final IndexingPolicy indexingPolicy; + private final boolean isVersioned; private boolean autoCreateContainer; /** diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java index d93afa8f2b75..cd027302ec74 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java @@ -26,14 +26,14 @@ public class CosmosDbFactoryTestIT { @Test(expected = IllegalArgumentException.class) public void testEmptyKey() { - final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_HOST, "", DB_NAME).build(); + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, "", DB_NAME).build(); new CosmosDbFactory(dbConfig); } @Test public void testInvalidEndpoint() { final CosmosDBConfig dbConfig = - CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build(); + CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); assertThat(factory).isNotNull(); @@ -42,7 +42,7 @@ public void testInvalidEndpoint() { @Test public void testConnectWithConnectionString() { final CosmosDBConfig dbConfig = - CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build(); + CosmosDBConfig.builder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); assertThat(factory).isNotNull(); @@ -50,13 +50,13 @@ public void testConnectWithConnectionString() { @Test(expected = CosmosDBAccessException.class) public void testInvalidConnectionString() { - CosmosDBConfig.cosmosDBConfigbuilder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build(); + CosmosDBConfig.builder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build(); } @Test public void testConnectionPolicyUserAgentKept() { final CosmosDBConfig dbConfig = - CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, DB_NAME).build(); + CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); factory.getCosmosClient(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java index ff87d30ab73b..3714460b8996 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java @@ -29,7 +29,7 @@ public class UserAgentTestIT { public void testUserAgentSuffixAppended() { PowerMockito.mockStatic(PropertyLoader.class); Mockito.doReturn(TEST_VERSION).when(PropertyLoader.getProjectVersion()); - final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(TestConstants.COSMOSDB_FAKE_HOST, + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(TestConstants.COSMOSDB_FAKE_HOST, TestConstants.COSMOSDB_FAKE_KEY, TestConstants.DB_NAME).build(); final CosmosDbFactory factory = new CosmosDbFactory(dbConfig); factory.getCosmosClient(); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java index 19d6f5237f0f..a3fdd33fc4ef 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java @@ -101,7 +101,7 @@ static class TestCosmosConfiguration extends AbstractCosmosConfiguration { @Bean public CosmosDBConfig getConfig() { final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; - return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName).build(); + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName).build(); } @Override @@ -144,7 +144,7 @@ private RequestOptions getRequestOptions() { public CosmosDBConfig getConfig() { final String dbName = StringUtils.hasText(this.database) ? this.database : TestConstants.DB_NAME; final RequestOptions options = getRequestOptions(); - return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName) + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName) .requestOptions(options) .build(); } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java index bc894d494d8a..09e796d184ec 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java @@ -15,7 +15,7 @@ public class CosmosTemplateUnitTest { @Test(expected = IllegalArgumentException.class) public void rejectNullDbFactory() { - final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder("", "", TestConstants.DB_NAME).build(); + final CosmosDBConfig dbConfig = CosmosDBConfig.builder("", "", TestConstants.DB_NAME).build(); final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig); new CosmosTemplate(cosmosDbFactory, null, TestConstants.DB_NAME); diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java index 04cc2a353779..d893bbc89282 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java @@ -23,6 +23,6 @@ public class PerfConfiguration extends AbstractCosmosConfiguration { @Bean public CosmosDBConfig getConfig() { - return CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build(); + return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build(); } } diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java index 6b10fb9e4172..7079a4683ec6 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java @@ -60,9 +60,9 @@ public CosmosDBConfig getConfig() { if (StringUtils.hasText(this.cosmosDbUri) && StringUtils.hasText(this.cosmosDbKey)) { - builder = CosmosDBConfig.cosmosDBConfigbuilder(cosmosDbUri, cosmosDbKey, dbName); + builder = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, dbName); } else { - builder = CosmosDBConfig.cosmosDBConfigbuilder(connectionString, dbName); + builder = CosmosDBConfig.builder(connectionString, dbName); } return builder.requestOptions(options) .populateQueryMetrics(populateQueryMetrics) diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java index d97f910d6b4a..ab8965c8b67d 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java +++ b/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java @@ -83,7 +83,7 @@ public void testDynamicContainerNameWithBeanExpression() { @Test public void testDatabaseOperationsOnDynamicallyNamedCollection() throws ClassNotFoundException { - final CosmosDBConfig dbConfig = CosmosDBConfig.cosmosDBConfigbuilder(dbUri, dbKey, TestConstants.DB_NAME).build(); + final CosmosDBConfig dbConfig = CosmosDBConfig.builder(dbUri, dbKey, TestConstants.DB_NAME).build(); final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig); cosmosEntityInformation = new CosmosEntityInformation<>(SpELPropertyStudent.class); From 4d404db0ef065b45d655a67b38b122fe89679904 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Wed, 17 Jun 2020 18:13:16 +0800 Subject: [PATCH 08/17] add changelog --- sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md diff --git a/sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md b/sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md new file mode 100644 index 000000000000..d98c3d0f2282 --- /dev/null +++ b/sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md @@ -0,0 +1,3 @@ +# Release History + +## 2.3.1-beta.1 (Unreleased) From 89776ce33644f797454868260d56a96f51ad7772 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 18 Jun 2020 09:50:16 +0800 Subject: [PATCH 09/17] modify for dependency version --- eng/jacoco-test-coverage/pom.xml | 5 ++ eng/versioning/external_dependencies.txt | 8 +-- .../pom.xml | 4 +- sdk/spring/azure-spring-boot/pom.xml | 6 -- .../QueryPartitionedCollection.md | 58 ------------------- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 26 +++++---- sdk/spring/ci.yml | 3 + 7 files changed, 27 insertions(+), 83 deletions(-) delete mode 100644 sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md diff --git a/eng/jacoco-test-coverage/pom.xml b/eng/jacoco-test-coverage/pom.xml index b07e392a1911..13940326009b 100644 --- a/eng/jacoco-test-coverage/pom.xml +++ b/eng/jacoco-test-coverage/pom.xml @@ -243,6 +243,11 @@ azure-data-gremlin-spring-boot-starter 2.3.3-beta.1 + + com.microsoft.azure + spring-data-cosmosdb + 2.3.1-beta.1 + diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index 541816968166..b91cc98828eb 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -17,7 +17,7 @@ com.microsoft.azure:azure-arm-client-runtime;1.7.3 com.microsoft.azure:azure-client-authentication;1.7.3 com.microsoft.azure:azure-client-runtime;1.7.3 com.microsoft.azure:azure-core;0.9.8 -com.microsoft.azure:azure-cosmos;3.7.1 +com.microsoft.azure:azure-cosmos;3.7.3 com.microsoft.azure:azure-keyvault-cryptography;1.2.2 com.microsoft.azure:azure-media;0.9.8 com.microsoft.azure:azure-servicebus-jms;0.0.2 @@ -65,7 +65,6 @@ org.powermock:powermock-api-mockito2;2.0.2 org.powermock:powermock-module-junit4;2.0.2 org.slf4j:slf4j-api;1.7.28 org.slf4j:slf4j-simple;1.7.25 -<<<<<<< HEAD ## Spring boot dependency versions org.springframework.boot:spring-boot-starter-actuator;2.3.0.RELEASE @@ -268,8 +267,3 @@ spring_io.micrometer:micrometer-core;1.3.0 spring_io.micrometer:micrometer-registry-azure-monitor;1.3.0 spring_com.microsoft.azure:azure;1.34.0 -#sdk\spring\spring-data-cosmosdb\pom.xml -spring_org.springframework:spring-web;5.2.6.RELEASE -spring_com.microsoft.azure:azure-cosmos;3.7.3 -spring_org.springframework.boot:spring-boot-starter-test;2.3.0.RELEASE - diff --git a/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml b/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml index 009481b70cc7..6e5254e20170 100644 --- a/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml @@ -38,7 +38,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.2.3.FIX1 + 2.3.1-beta.1 @@ -53,7 +53,7 @@ com.microsoft.azure:azure-spring-boot:[2.3.3-beta.1] - com.microsoft.azure:spring-data-cosmosdb:[2.2.3.FIX1] + com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] org.springframework.boot:spring-boot-starter:[2.3.0.RELEASE] org.springframework.boot:spring-boot-starter-validation:[2.3.0.RELEASE] diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index 353c7c2c9cd1..1c6f4470ac2a 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -250,12 +250,6 @@ 1.1.1 test - - com.azure - azure-identity - 1.0.4 - compile - diff --git a/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md b/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md deleted file mode 100644 index 1c0d04129e7d..000000000000 --- a/sdk/spring/azure-spring-data-cosmosdb/QueryPartitionedCollection.md +++ /dev/null @@ -1,58 +0,0 @@ -### How to Query Partitioned Azure Cosmos DB Collection - -With Azure Cosmos DB, you can configure [partition key](https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data) for your collection. - -Below is an example about how to query partitioned collection with this spring data module. - -#### Example - -Given a document entity structure: -``` - @Document - @Data - @AllArgsConstructor - public class Address { - @Id - String postalCode; - String street; - @PartitionKey - String city; - } -``` - -Write the repository interface: -``` - @Repository - public interface AddressRepository extends DocumentDbRepository { - // Add query methods here, refer to below - } -``` - -Query by field name: -``` - List
findByCity(String city); -``` - -Delete by field name: -``` - void deleteByStreet(String street); -``` - -For `Partitioned collection`, if you want to query records by `findById(id)`, exception will be thrown. -``` - // Incorrect for partitioned collection, exception will be thrown - Address result = repository.findById(id); // Caution: Works for non-partitioned collection -``` - -Instead, you can query records by ID field name with custom query. -``` - // Correct, postalCode is the ID field in Address domain - @Repository - public interface AddressRepository extends DocumentDbRepository { - List
findByPostalCode(String postalCode); - } - - // Query - List
result = repository.findByPostalCode(postalCode); -``` - diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 4fd17b2aa20c..cf5244e81a94 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -44,7 +44,7 @@ org.springframework spring-web - 5.2.6.RELEASE + 5.2.6.RELEASE @@ -79,7 +79,7 @@ com.microsoft.azure azure-cosmos - 3.7.3 + 3.7.3 @@ -131,7 +131,7 @@ org.springframework.boot spring-boot-starter-test - 2.3.0.RELEASE + 2.3.0.RELEASE test @@ -183,13 +183,19 @@ - org.springframework:*:5.2.6.RELEASE - org.springframework.data:spring-data-commons:2.3.0.RELEASE - com.microsoft.azure:azure-cosmos:3.7.3 - org.javatuples:javatuples:1.2 - com.fasterxml.jackson.datatype:*:2.10.0 - org.json:json:20140107 - com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.0 + org.springframework:spring-beans:[5.2.6.RELEASE] + org.springframework:spring-web:[5.2.6.RELEASE] + org.springframework:spring-tx:[5.2.6.RELEASE] + org.springframework:spring-expression:[5.2.6.RELEASE] + org.springframework:spring-core:[5.2.6.RELEASE] + org.springframework:spring-context:[5.2.6.RELEASE] + org.springframework.data:spring-data-commons:[2.3.0.RELEASE] + com.microsoft.azure:azure-cosmos:[3.7.3] + org.javatuples:javatuples:[1.2] + com.fasterxml.jackson.datatype:jackson-datatype-jdk8:[2.10.0] + com.fasterxml.jackson.datatype:jackson-datatype-jsr310:[2.10.1] + org.json:json:[20140107] + com.fasterxml.jackson.module:jackson-module-parameter-names:[2.10.0] org.slf4j:slf4j-simple:[1.7.25] diff --git a/sdk/spring/ci.yml b/sdk/spring/ci.yml index 7ccde32252d2..cb8096ad8aff 100644 --- a/sdk/spring/ci.yml +++ b/sdk/spring/ci.yml @@ -55,6 +55,9 @@ extends: - name: azure-servicebus-jms-spring-boot-starter groupId: com.microsoft.azure safeName: azurespringbootstarterservicebusjms + - name: spring-data-cosmosdb + groupId: com.microsoft.azure + safeName: springdatacosmosdb AdditionalModules: - name: azure-spring-boot-samples groupId: com.microsoft.azure From f2543cb65acce54dd92bebd239281ad06ac056f3 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 18 Jun 2020 11:25:19 +0800 Subject: [PATCH 10/17] modify readme title and add dependency for java11 --- sdk/spring/azure-spring-data-cosmosdb/README.md | 2 +- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/spring/azure-spring-data-cosmosdb/README.md index 0005be53ddb6..d8dd48270e87 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/README.md +++ b/sdk/spring/azure-spring-data-cosmosdb/README.md @@ -3,7 +3,7 @@ [![MIT License](http://img.shields.io/badge/license-MIT-green.svg) ](https://github.com/Microsoft/spring-data-cosmosdb/blob/master/LICENSE) -# Spring Data for Azure Cosmos DB +#Azure Spring Data client library of Azure Cosmos DB for Java [Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction) is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as SQL, MongoDB, Cassandra, Graph, and Table. diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index cf5244e81a94..4cba727b14d5 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -109,6 +109,12 @@ 1.2 + + javax.annotation + javax.annotation-api + 1.3.2 + + org.mockito @@ -196,6 +202,7 @@ com.fasterxml.jackson.datatype:jackson-datatype-jsr310:[2.10.1] org.json:json:[20140107] com.fasterxml.jackson.module:jackson-module-parameter-names:[2.10.0] + javax.annotation:javax.annotation-api:[1.3.2] org.slf4j:slf4j-simple:[1.7.25] From 97f6ca204315212c650a5e9652569761ea879d7c Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 18 Jun 2020 14:02:37 +0800 Subject: [PATCH 11/17] add code owner --- .github/CODEOWNERS | 1 + sdk/spring/azure-spring-data-cosmosdb/README.md | 2 +- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4d0c51fa5a55..4e2ba472ab46 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -26,6 +26,7 @@ /sdk/storage/ @amishra-dev @rickle-msft @jaschrep-msft @gapra-msft @alzimmermsft @sima-zhu /sdk/textanalytics/ @samvaity @mssfang @sima-zhu /sdk/spring/ @saragluna @yiliuTo @chenrujun @jialindai +/sdk/spring/azure-spring-data-cosmosdb @kushagraThapar # end to end tests /sdk/e2e/ @jianghaolu @g2vinay diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/spring/azure-spring-data-cosmosdb/README.md index d8dd48270e87..7aa9df722953 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/README.md +++ b/sdk/spring/azure-spring-data-cosmosdb/README.md @@ -3,7 +3,7 @@ [![MIT License](http://img.shields.io/badge/license-MIT-green.svg) ](https://github.com/Microsoft/spring-data-cosmosdb/blob/master/LICENSE) -#Azure Spring Data client library of Azure Cosmos DB for Java +#Azure Cosmos DB client library for Java [Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction) is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as SQL, MongoDB, Cassandra, Graph, and Table. diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 4cba727b14d5..014d34832b88 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -20,6 +20,7 @@ MM-dd-HH-mm-ss + 0.22 spring-data-cosmosdb-test testdb-${maven.build.timestamp} From 53fa59e422b904755f538f5c64b5ab9a017f5c7e Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 18 Jun 2020 16:06:53 +0800 Subject: [PATCH 12/17] add debug for pipeline error temporarily --- .../templates/jobs/archetype-sdk-client.yml | 3 ++- .../azure-spring-data-cosmosdb/README.md | 19 +++++++++++++------ sdk/spring/azure-spring-data-cosmosdb/pom.xml | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/eng/pipelines/templates/jobs/archetype-sdk-client.yml b/eng/pipelines/templates/jobs/archetype-sdk-client.yml index c1facca7d206..6cce4bdb8f6a 100644 --- a/eng/pipelines/templates/jobs/archetype-sdk-client.yml +++ b/eng/pipelines/templates/jobs/archetype-sdk-client.yml @@ -27,6 +27,7 @@ parameters: OSVmImage: 'macOS-10.15' JavaTestVersion: '1.11' RunTitle: 'macOS on Java 1.11' + AdditionalOptions: '-X' Windows - Java 11: OSVmImage: 'windows-2019' JavaTestVersion: '1.11' @@ -36,7 +37,7 @@ parameters: JavaTestVersion: '1.8' RunTitle: 'From Source: Windows on Java 1.8' PLSkipOptions: '!com.azure:jacoco-test-coverage' - AdditionalOptions: '-amd' + AdditionalOptions: '-amd -X' TestFromSource: true jobs: diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/spring/azure-spring-data-cosmosdb/README.md index 7aa9df722953..c181d5b5ff53 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/README.md +++ b/sdk/spring/azure-spring-data-cosmosdb/README.md @@ -5,23 +5,26 @@ #Azure Cosmos DB client library for Java +## Getting started [Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction) is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as SQL, MongoDB, Cassandra, Graph, and Table. **Spring Data Azure Cosmos DB** provides initial Spring Data support for Azure Cosmos DB using the [SQL API](https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-introduction), based on Spring Data framework. Currently it only supports SQL API, the other APIs are in the plan. ## TOC -* [Sample Code](#sample-code) +* [Examples](#Examples) * [Spring data version support](#spring-data-version-support) * [Feature List](#feature-list) * [Quick Start](#quick-start) * [Query Partitioned Collection](QueryPartitionedCollection.md) * [Snapshots](#snapshots) -* [Filing Issues](#filing-issues) -* [How to Contribute](#how-to-contribute) +* [Troubleshooting](#Troubleshooting) +* [Contributing](#Contributing) * [Code of Conduct](#code-of-conduct) +* [Key concepts](#Key concepts) +* [Next steps](#Next steps) -## Sample Code +## Examples Please refer to [sample project here](./samplecode). ## Spring Data Version Support @@ -316,13 +319,13 @@ Snapshots built from `master` branch are available, add [maven repositories](htt ``` -## Filing Issues +## Troubleshooting If you encounter any bug, please file an issue [here](https://github.com/Microsoft/spring-data-cosmosdb/issues/new). To suggest a new feature or changes that could be made, file an issue the same way you would for a bug. -## How To Contribute +## Contributing Contribution is welcome. Please follow [this instruction](https://github.com/Azure/azure-sdk-for-java/blob/master/CONTRIBUTING.md) to contribute code. @@ -333,3 +336,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope ### Data/Telemetry This project collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy](https://privacy.microsoft.com/en-us/privacystatement) statement to learn more. + +## Key concepts + +## Next steps diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index 014d34832b88..d6a968bb579e 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -21,6 +21,7 @@ MM-dd-HH-mm-ss 0.22 + 0.22 spring-data-cosmosdb-test testdb-${maven.build.timestamp} From 699ba12f666fa949181ee6d0af2c46c5d1720d0c Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Thu, 18 Jun 2020 17:47:17 +0800 Subject: [PATCH 13/17] add dependency in cosmos for running java-core-ci --- eng/pipelines/templates/jobs/archetype-sdk-client.yml | 3 +-- sdk/spring/azure-spring-data-cosmosdb/pom.xml | 11 +++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/templates/jobs/archetype-sdk-client.yml b/eng/pipelines/templates/jobs/archetype-sdk-client.yml index 6cce4bdb8f6a..c1facca7d206 100644 --- a/eng/pipelines/templates/jobs/archetype-sdk-client.yml +++ b/eng/pipelines/templates/jobs/archetype-sdk-client.yml @@ -27,7 +27,6 @@ parameters: OSVmImage: 'macOS-10.15' JavaTestVersion: '1.11' RunTitle: 'macOS on Java 1.11' - AdditionalOptions: '-X' Windows - Java 11: OSVmImage: 'windows-2019' JavaTestVersion: '1.11' @@ -37,7 +36,7 @@ parameters: JavaTestVersion: '1.8' RunTitle: 'From Source: Windows on Java 1.8' PLSkipOptions: '!com.azure:jacoco-test-coverage' - AdditionalOptions: '-amd -X' + AdditionalOptions: '-amd' TestFromSource: true jobs: diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/spring/azure-spring-data-cosmosdb/pom.xml index d6a968bb579e..e9b7ce89184a 100644 --- a/sdk/spring/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-data-cosmosdb/pom.xml @@ -20,8 +20,8 @@ MM-dd-HH-mm-ss - 0.22 - 0.22 + 0.17 + 0.18 spring-data-cosmosdb-test testdb-${maven.build.timestamp} @@ -169,6 +169,12 @@ 2.8.5 test + + + com.azure + azure-identity + 1.0.7 + @@ -191,6 +197,7 @@ + com.azure:* org.springframework:spring-beans:[5.2.6.RELEASE] org.springframework:spring-web:[5.2.6.RELEASE] org.springframework:spring-tx:[5.2.6.RELEASE] From ce265b70bd7401734c058752829b4fac81845b25 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Mon, 22 Jun 2020 13:44:29 +0800 Subject: [PATCH 14/17] move spring-data-cosmosdb to sdk/cosmos --- eng/versioning/external_dependencies.txt | 1 - .../azure-spring-data-cosmosdb/CHANGELOG.md | 0 sdk/{spring => cosmos}/azure-spring-data-cosmosdb/README.md | 0 sdk/{spring => cosmos}/azure-spring-data-cosmosdb/pom.xml | 0 .../com.microsoft.azure.spring.data.cosmosdb/Constants.java | 0 .../CosmosDbFactory.java | 0 .../common/CosmosdbUtils.java | 0 .../common/ExpressionResolver.java | 0 .../common/MacAddress.java | 0 .../common/Memoizer.java | 0 .../common/PropertyLoader.java | 0 .../common/TelemetryEventData.java | 0 .../common/TelemetrySender.java | 0 .../common/package-info.java | 0 .../config/AbstractCosmosConfiguration.java | 0 .../config/CosmosConfigurationSupport.java | 0 .../config/CosmosDBConfig.java | 0 .../config/package-info.java | 0 .../core/CosmosOperations.java | 0 .../core/CosmosTemplate.java | 0 .../core/ReactiveCosmosOperations.java | 0 .../core/ReactiveCosmosTemplate.java | 0 .../core/ResponseDiagnostics.java | 0 .../core/ResponseDiagnosticsProcessor.java | 0 .../core/convert/MappingCosmosConverter.java | 0 .../core/convert/ObjectMapperFactory.java | 0 .../core/convert/package-info.java | 0 .../core/generator/AbstractQueryGenerator.java | 0 .../core/generator/CountQueryGenerator.java | 0 .../core/generator/FindQuerySpecGenerator.java | 0 .../core/generator/QuerySpecGenerator.java | 0 .../core/generator/package-info.java | 0 .../core/mapping/BasicCosmosPersistentEntity.java | 0 .../core/mapping/BasicCosmosPersistentProperty.java | 0 .../core/mapping/CosmosMappingContext.java | 0 .../core/mapping/CosmosPersistentEntity.java | 0 .../core/mapping/CosmosPersistentProperty.java | 0 .../core/mapping/Document.java | 0 .../core/mapping/DocumentIndexingPolicy.java | 0 .../core/mapping/PartitionKey.java | 0 .../core/mapping/package-info.java | 0 .../core/package-info.java | 0 .../core/query/CosmosPageImpl.java | 0 .../core/query/CosmosPageRequest.java | 0 .../core/query/Criteria.java | 0 .../core/query/CriteriaType.java | 0 .../core/query/DocumentQuery.java | 0 .../core/query/package-info.java | 0 .../exception/ConfigurationException.java | 0 .../exception/CosmosDBAccessException.java | 0 .../exception/CosmosDBExceptionUtils.java | 0 .../exception/DatabaseCreationException.java | 0 .../exception/IllegalCollectionException.java | 0 .../exception/IllegalQueryException.java | 0 .../exception/package-info.java | 0 .../package-info.java | 0 .../repository/CosmosRepository.java | 0 .../repository/ReactiveCosmosRepository.java | 0 .../repository/config/CosmosRepositoriesRegistrar.java | 0 .../config/CosmosRepositoryConfigurationExtension.java | 0 .../repository/config/EnableCosmosRepositories.java | 0 .../repository/config/EnableReactiveCosmosRepositories.java | 0 .../config/ReactiveCosmosRepositoriesRegistrar.java | 0 .../ReactiveCosmosRepositoryConfigurationExtension.java | 0 .../repository/config/package-info.java | 0 .../repository/package-info.java | 0 .../repository/query/AbstractCosmosQuery.java | 0 .../repository/query/AbstractReactiveCosmosQuery.java | 0 .../repository/query/CosmosEntityMetadata.java | 0 .../repository/query/CosmosParameter.java | 0 .../repository/query/CosmosParameterAccessor.java | 0 .../repository/query/CosmosParameterParameterAccessor.java | 0 .../repository/query/CosmosParameters.java | 0 .../repository/query/CosmosQueryCreator.java | 0 .../repository/query/CosmosQueryExecution.java | 0 .../repository/query/CosmosQueryMethod.java | 0 .../repository/query/PartTreeCosmosQuery.java | 0 .../repository/query/PartTreeReactiveCosmosQuery.java | 0 .../repository/query/ReactiveCosmosEntityMetadata.java | 0 .../repository/query/ReactiveCosmosParameterAccessor.java | 0 .../query/ReactiveCosmosParameterParameterAccessor.java | 0 .../repository/query/ReactiveCosmosQueryCreator.java | 0 .../repository/query/ReactiveCosmosQueryExecution.java | 0 .../repository/query/ReactiveCosmosQueryMethod.java | 0 .../repository/query/SimpleCosmosEntityMetadata.java | 0 .../repository/query/SimpleReactiveCosmosEntityMetadata.java | 0 .../repository/query/package-info.java | 0 .../repository/support/CosmosEntityInformation.java | 0 .../repository/support/CosmosRepositoryFactory.java | 0 .../repository/support/CosmosRepositoryFactoryBean.java | 0 .../repository/support/ReactiveCosmosRepositoryFactory.java | 0 .../support/ReactiveCosmosRepositoryFactoryBean.java | 0 .../repository/support/SimpleCosmosRepository.java | 0 .../repository/support/SimpleReactiveCosmosRepository.java | 0 .../repository/support/package-info.java | 0 .../src/main/resources/META-INF/project.properties | 0 .../src/main/resources/META-INF/spring.factories | 0 .../src/main/resources/telemetry.config | 0 .../CosmosDbFactoryTestIT.java | 0 .../UserAgentTestIT.java | 0 .../common/DynamicContainer.java | 0 .../common/ExpressionResolverUnitTest.java | 0 .../common/MemoizerUnitTest.java | 0 .../common/PageTestUtils.java | 0 .../common/PropertyLoaderUnitTest.java | 0 .../common/ResponseDiagnosticsTestUtils.java | 0 .../common/TestConstants.java | 0 .../common/TestUtils.java | 0 .../config/AbstractCosmosConfigurationIT.java | 0 .../core/CosmosTemplateIT.java | 0 .../core/CosmosTemplateIllegalTest.java | 0 .../core/CosmosTemplatePartitionIT.java | 0 .../core/CosmosTemplateUnitTest.java | 0 .../core/ReactiveCosmosTemplateIT.java | 0 .../core/ReactiveCosmosTemplatePartitionIT.java | 0 .../core/convert/ZonedDateTimeDeserializerTest.java | 0 .../core/converter/MappingCosmosConverterUnitTest.java | 0 .../core/mapping/BasicCosmosPersistentEntityUnitTest.java | 0 .../core/mapping/CosmosMappingContextUnitTest.java | 0 .../core/query/CriteriaUnitTest.java | 0 .../core/query/DocumentQueryUnitTest.java | 0 .../domain/Address.java | 0 .../domain/Contact.java | 0 .../domain/Course.java | 0 .../domain/Customer.java | 0 .../domain/Importance.java | 0 .../domain/IntegerIdDomain.java | 0 .../domain/Memo.java | 0 .../domain/NoDBAnnotationPerson.java | 0 .../domain/PageableAddress.java | 0 .../domain/PageableMemo.java | 0 .../domain/PageablePerson.java | 0 .../domain/PartitionPerson.java | 0 .../domain/Person.java | 0 .../domain/Project.java | 0 .../domain/Question.java | 0 .../domain/Role.java | 0 .../domain/SortedProject.java | 0 .../domain/SpELBeanStudent.java | 0 .../domain/SpELPropertyStudent.java | 0 .../domain/Student.java | 0 .../domain/TimeToLiveSample.java | 0 .../domain/inheritance/Shape.java | 0 .../domain/inheritance/Square.java | 0 .../performance/PerfConfiguration.java | 0 .../performance/PerformanceCompare.java | 0 .../performance/PerformanceReport.java | 0 .../performance/domain/PerfPerson.java | 0 .../performance/repository/PerfPersonRepository.java | 0 .../performance/service/SdkService.java | 0 .../performance/utils/Constants.java | 0 .../performance/utils/DatabaseUtils.java | 0 .../performance/utils/FunctionUtils.java | 0 .../performance/utils/PerfDataProvider.java | 0 .../repository/CosmosAnnotationUnitTest.java | 0 .../repository/SimpleCosmosRepositoryIllegalTest.java | 0 .../repository/SimpleCosmosRepositoryUnitTest.java | 0 .../repository/TestRepositoryConfig.java | 0 .../CosmosRepositoryConfigurationExtensionUnitTest.java | 0 ...activeCosmosRepositoryConfigurationExtensionUnitTest.java | 0 .../repository/integration/AddressRepositoryIT.java | 0 .../repository/integration/ContactRepositoryIT.java | 0 .../repository/integration/CosmosAnnotationIT.java | 0 .../repository/integration/CustomerRepositoryIT.java | 0 .../repository/integration/IntegerIdDomainRepositoryIT.java | 0 .../repository/integration/MemoRepositoryIT.java | 0 .../repository/integration/PageableAddressRepositoryIT.java | 0 .../repository/integration/PageableMemoRepositoryIT.java | 0 .../repository/integration/PageablePersonRepositoryIT.java | 0 .../repository/integration/PersonRepositoryIT.java | 0 .../repository/integration/ProjectRepositoryIT.java | 0 .../repository/integration/ProjectRepositorySortIT.java | 0 .../repository/integration/QuestionRepositoryIT.java | 0 .../repository/integration/ReactiveCourseRepositoryIT.java | 0 .../repository/integration/SpELCosmosDBAnnotationIT.java | 0 .../repository/integration/SquareRepositoryIT.java | 0 .../repository/integration/StudentRepositoryIT.java | 0 .../repository/repository/AddressRepository.java | 0 .../repository/repository/ContactRepository.java | 0 .../repository/repository/CustomerRepository.java | 0 .../repository/repository/IntegerIdDomainRepository.java | 0 .../repository/repository/MemoRepository.java | 0 .../repository/repository/PageableAddressRepository.java | 0 .../repository/repository/PageableMemoRepository.java | 0 .../repository/repository/PageablePersonRepository.java | 0 .../repository/repository/PartitionPersonRepository.java | 0 .../repository/repository/PersonRepository.java | 0 .../repository/repository/ProjectRepository.java | 0 .../repository/repository/QuestionRepository.java | 0 .../repository/repository/ReactiveCourseRepository.java | 0 .../repository/repository/SortedProjectRepository.java | 0 .../repository/repository/SquareRepository.java | 0 .../repository/repository/StudentRepository.java | 0 .../repository/support/CosmosEntityInformationUnitTest.java | 0 .../support/CosmosRepositoryFactoryBeanUnitTest.java | 0 .../repository/support/CosmosRepositoryFactoryUnitTest.java | 0 .../src/test/resources/application.properties | 0 .../src/test/resources/application.yml | 0 .../src/test/resources/logback-test.xml | 0 sdk/cosmos/ci.yml | 5 ++++- sdk/spring/azure-spring-boot/pom.xml | 4 ++-- sdk/spring/ci.yml | 3 --- sdk/spring/pom.xml | 1 - 203 files changed, 6 insertions(+), 8 deletions(-) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/CHANGELOG.md (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/README.md (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/pom.xml (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/main/resources/telemetry.config (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/resources/application.properties (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/resources/application.yml (100%) rename sdk/{spring => cosmos}/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml (100%) diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index b91cc98828eb..c04ed1143ad8 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -22,7 +22,6 @@ com.microsoft.azure:azure-keyvault-cryptography;1.2.2 com.microsoft.azure:azure-media;0.9.8 com.microsoft.azure:azure-servicebus-jms;0.0.2 com.microsoft.azure:qpid-proton-j-extensions;1.2.3 -com.microsoft.azure:spotbugs-maven-plugin;1.2.1 com.microsoft.rest:client-runtime;1.7.4 com.microsoft.rest.v2:client-runtime;2.1.1 com.microsoft.spring.data.gremlin:spring-data-gremlin;2.2.3 diff --git a/sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md b/sdk/cosmos/azure-spring-data-cosmosdb/CHANGELOG.md similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/CHANGELOG.md rename to sdk/cosmos/azure-spring-data-cosmosdb/CHANGELOG.md diff --git a/sdk/spring/azure-spring-data-cosmosdb/README.md b/sdk/cosmos/azure-spring-data-cosmosdb/README.md similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/README.md rename to sdk/cosmos/azure-spring-data-cosmosdb/README.md diff --git a/sdk/spring/azure-spring-data-cosmosdb/pom.xml b/sdk/cosmos/azure-spring-data-cosmosdb/pom.xml similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/pom.xml rename to sdk/cosmos/azure-spring-data-cosmosdb/pom.xml diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/Constants.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactory.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/CosmosdbUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolver.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/MacAddress.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/Memoizer.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoader.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetryEventData.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/TelemetrySender.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/common/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfiguration.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosConfigurationSupport.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/CosmosDBConfig.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/config/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosOperations.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplate.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosOperations.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplate.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnostics.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/ResponseDiagnosticsProcessor.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/MappingCosmosConverter.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ObjectMapperFactory.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/AbstractQueryGenerator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/CountQueryGenerator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/FindQuerySpecGenerator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/QuerySpecGenerator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/generator/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntity.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentProperty.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContext.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentEntity.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosPersistentProperty.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/Document.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/DocumentIndexingPolicy.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/PartitionKey.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageImpl.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CosmosPageRequest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/Criteria.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaType.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQuery.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/core/query/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/ConfigurationException.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBAccessException.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/CosmosDBExceptionUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/DatabaseCreationException.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalCollectionException.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/IllegalQueryException.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/exception/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/ReactiveCosmosRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoriesRegistrar.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtension.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableCosmosRepositories.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/EnableReactiveCosmosRepositories.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoriesRegistrar.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtension.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractCosmosQuery.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/AbstractReactiveCosmosQuery.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosEntityMetadata.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameter.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterAccessor.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameterParameterAccessor.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosParameters.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryCreator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryExecution.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/CosmosQueryMethod.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeCosmosQuery.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/PartTreeReactiveCosmosQuery.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosEntityMetadata.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterAccessor.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosParameterParameterAccessor.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryCreator.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryExecution.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/ReactiveCosmosQueryMethod.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleCosmosEntityMetadata.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/SimpleReactiveCosmosEntityMetadata.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/query/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformation.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactory.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBean.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactory.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/ReactiveCosmosRepositoryFactoryBean.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleCosmosRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/SimpleReactiveCosmosRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/package-info.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/META-INF/project.properties diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/META-INF/spring.factories diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config b/sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/telemetry.config similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/main/resources/telemetry.config rename to sdk/cosmos/azure-spring-data-cosmosdb/src/main/resources/telemetry.config diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/CosmosDbFactoryTestIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/UserAgentTestIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/DynamicContainer.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ExpressionResolverUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/MemoizerUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PageTestUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/PropertyLoaderUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/ResponseDiagnosticsTestUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestConstants.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/common/TestUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/config/AbstractCosmosConfigurationIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateIllegalTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplatePartitionIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/CosmosTemplateUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplateIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/ReactiveCosmosTemplatePartitionIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/convert/ZonedDateTimeDeserializerTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/converter/MappingCosmosConverterUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/BasicCosmosPersistentEntityUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/mapping/CosmosMappingContextUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/CriteriaUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/core/query/DocumentQueryUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Address.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Contact.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Course.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Customer.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Importance.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/IntegerIdDomain.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Memo.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/NoDBAnnotationPerson.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableAddress.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageableMemo.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PageablePerson.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/PartitionPerson.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Person.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Project.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Question.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Role.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SortedProject.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELBeanStudent.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/SpELPropertyStudent.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/Student.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/TimeToLiveSample.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Shape.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/domain/inheritance/Square.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerfConfiguration.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceCompare.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/PerformanceReport.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/domain/PerfPerson.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/repository/PerfPersonRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/service/SdkService.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/Constants.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/DatabaseUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/FunctionUtils.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/performance/utils/PerfDataProvider.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/CosmosAnnotationUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryIllegalTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/SimpleCosmosRepositoryUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/TestRepositoryConfig.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/CosmosRepositoryConfigurationExtensionUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/config/ReactiveCosmosRepositoryConfigurationExtensionUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/AddressRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ContactRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CosmosAnnotationIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/CustomerRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/IntegerIdDomainRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/MemoRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableAddressRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageableMemoRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PageablePersonRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/PersonRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ProjectRepositorySortIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/QuestionRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/ReactiveCourseRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SpELCosmosDBAnnotationIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/SquareRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/integration/StudentRepositoryIT.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/AddressRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ContactRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/CustomerRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/IntegerIdDomainRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/MemoRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableAddressRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageableMemoRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PageablePersonRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PartitionPersonRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/PersonRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ProjectRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/QuestionRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/ReactiveCourseRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SortedProjectRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/SquareRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/repository/StudentRepository.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosEntityInformationUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryBeanUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/java/com.microsoft.azure.spring.data.cosmosdb/repository/support/CosmosRepositoryFactoryUnitTest.java diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/application.properties similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.properties rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/application.properties diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/application.yml similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/resources/application.yml rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/application.yml diff --git a/sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml b/sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml similarity index 100% rename from sdk/spring/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml rename to sdk/cosmos/azure-spring-data-cosmosdb/src/test/resources/logback-test.xml diff --git a/sdk/cosmos/ci.yml b/sdk/cosmos/ci.yml index 956cef15a89f..5fda6a2dcdf8 100644 --- a/sdk/cosmos/ci.yml +++ b/sdk/cosmos/ci.yml @@ -43,6 +43,9 @@ extends: - name: azure-cosmos groupId: com.azure safeName: azurecosmos + - name: spring-data-cosmosdb + groupId: com.microsoft.azure + safeName: springdatacosmosdb AdditionalModules: - name: azure-cosmos-benchmark - groupId: com.azure \ No newline at end of file + groupId: com.azure diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index 1c6f4470ac2a..2160c4126b76 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -116,7 +116,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.3.1-beta.1 + 2.3.1-beta.1 true @@ -268,7 +268,7 @@ net.minidev:json-smart:[2.3] com.microsoft.azure:azure-servicebus-jms:[0.0.2] com.microsoft.azure:msal4j:[1.3.0] - com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] + com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] com.microsoft.spring.data.gremlin:spring-data-gremlin:[2.2.3] com.nimbusds:nimbus-jose-jwt:[7.9] io.micrometer:micrometer-core:[1.3.0] diff --git a/sdk/spring/ci.yml b/sdk/spring/ci.yml index cb8096ad8aff..7ccde32252d2 100644 --- a/sdk/spring/ci.yml +++ b/sdk/spring/ci.yml @@ -55,9 +55,6 @@ extends: - name: azure-servicebus-jms-spring-boot-starter groupId: com.microsoft.azure safeName: azurespringbootstarterservicebusjms - - name: spring-data-cosmosdb - groupId: com.microsoft.azure - safeName: springdatacosmosdb AdditionalModules: - name: azure-spring-boot-samples groupId: com.microsoft.azure diff --git a/sdk/spring/pom.xml b/sdk/spring/pom.xml index 0f714b4b2faf..b9e7c1e1216c 100644 --- a/sdk/spring/pom.xml +++ b/sdk/spring/pom.xml @@ -20,7 +20,6 @@ azure-spring-boot-starter-servicebus-jms azure-spring-boot-samples azure-spring-boot-tests - azure-spring-data-cosmosdb From abfa961210570d902bd3d90426e04e30babcb7c3 Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Mon, 22 Jun 2020 14:17:29 +0800 Subject: [PATCH 15/17] fix for the pipeline --- sdk/cosmos/azure-spring-data-cosmosdb/pom.xml | 6 ------ sdk/cosmos/pom.xml | 1 + sdk/spring/azure-spring-boot/pom.xml | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sdk/cosmos/azure-spring-data-cosmosdb/pom.xml b/sdk/cosmos/azure-spring-data-cosmosdb/pom.xml index e9b7ce89184a..c173ad25dd9a 100644 --- a/sdk/cosmos/azure-spring-data-cosmosdb/pom.xml +++ b/sdk/cosmos/azure-spring-data-cosmosdb/pom.xml @@ -169,12 +169,6 @@ 2.8.5 test - - - com.azure - azure-identity - 1.0.7 - diff --git a/sdk/cosmos/pom.xml b/sdk/cosmos/pom.xml index 3cb34026e472..3ef7f2e8daa9 100644 --- a/sdk/cosmos/pom.xml +++ b/sdk/cosmos/pom.xml @@ -11,6 +11,7 @@ azure-cosmos azure-cosmos-benchmark + azure-spring-data-cosmosdb diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index 2160c4126b76..6609209f50e9 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -116,7 +116,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.3.1-beta.1 + 2.3.0 true @@ -268,7 +268,7 @@ net.minidev:json-smart:[2.3] com.microsoft.azure:azure-servicebus-jms:[0.0.2] com.microsoft.azure:msal4j:[1.3.0] - com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] + com.microsoft.azure:spring-data-cosmosdb:[2.3.0] com.microsoft.spring.data.gremlin:spring-data-gremlin:[2.2.3] com.nimbusds:nimbus-jose-jwt:[7.9] io.micrometer:micrometer-core:[1.3.0] From e2b8ba1d97179200349a39d6a6cab362fbd4f59b Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Mon, 22 Jun 2020 15:24:29 +0800 Subject: [PATCH 16/17] add spring-data-cosmosdb as external-dependency for pipeline --- eng/versioning/external_dependencies.txt | 1 + sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml | 4 ++-- sdk/spring/azure-spring-boot/pom.xml | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index c04ed1143ad8..37b8010866ff 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -25,6 +25,7 @@ com.microsoft.azure:qpid-proton-j-extensions;1.2.3 com.microsoft.rest:client-runtime;1.7.4 com.microsoft.rest.v2:client-runtime;2.1.1 com.microsoft.spring.data.gremlin:spring-data-gremlin;2.2.3 +com.microsoft.azure:spring-data-cosmosdb;2.3.0 com.squareup.okhttp3:okhttp;4.2.2 commons-codec:commons-codec;1.13 io.micrometer:micrometer-core;1.2.0 diff --git a/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml b/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml index 6e5254e20170..c4c36f84f876 100644 --- a/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml +++ b/sdk/spring/azure-spring-boot-starter-cosmosdb/pom.xml @@ -38,7 +38,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.3.1-beta.1 + 2.3.0 @@ -53,7 +53,7 @@ com.microsoft.azure:azure-spring-boot:[2.3.3-beta.1] - com.microsoft.azure:spring-data-cosmosdb:[2.3.1-beta.1] + com.microsoft.azure:spring-data-cosmosdb:[2.3.0] org.springframework.boot:spring-boot-starter:[2.3.0.RELEASE] org.springframework.boot:spring-boot-starter-validation:[2.3.0.RELEASE] diff --git a/sdk/spring/azure-spring-boot/pom.xml b/sdk/spring/azure-spring-boot/pom.xml index 6609209f50e9..e403ac72f0fc 100644 --- a/sdk/spring/azure-spring-boot/pom.xml +++ b/sdk/spring/azure-spring-boot/pom.xml @@ -116,7 +116,7 @@ com.microsoft.azure spring-data-cosmosdb - 2.3.0 + 2.3.0 true @@ -268,7 +268,7 @@ net.minidev:json-smart:[2.3] com.microsoft.azure:azure-servicebus-jms:[0.0.2] com.microsoft.azure:msal4j:[1.3.0] - com.microsoft.azure:spring-data-cosmosdb:[2.3.0] + com.microsoft.azure:spring-data-cosmosdb:[2.3.0] com.microsoft.spring.data.gremlin:spring-data-gremlin:[2.2.3] com.nimbusds:nimbus-jose-jwt:[7.9] io.micrometer:micrometer-core:[1.3.0] From 826c8eae2a0cd016fc9fe87c647a1493552b767d Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Mon, 22 Jun 2020 17:18:47 +0800 Subject: [PATCH 17/17] modify codeowner --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4e2ba472ab46..e97f0f63beb8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -17,6 +17,7 @@ /sdk/core/ @alzimmermsft @jianghaolu @srnagar @hemanttanwar @anuchandy /sdk/core/azure-core-tracing-opentelemetry/ @samvaity @alzimmermsft /sdk/cosmos/ @moderakh @kushagraThapar @David-Noble-at-work @kirankumarkolli @mbhaskar +/sdk/cosmos/azure-spring-data-cosmosdb/ @kushagraThapar /sdk/eventhubs/ @conniey @srnagar @mssfang /sdk/formrecognizer/ @samvaity @mssfang @sima-zhu /sdk/identity/ @schaabs @g2vinay @jianghaolu @@ -26,7 +27,6 @@ /sdk/storage/ @amishra-dev @rickle-msft @jaschrep-msft @gapra-msft @alzimmermsft @sima-zhu /sdk/textanalytics/ @samvaity @mssfang @sima-zhu /sdk/spring/ @saragluna @yiliuTo @chenrujun @jialindai -/sdk/spring/azure-spring-data-cosmosdb @kushagraThapar # end to end tests /sdk/e2e/ @jianghaolu @g2vinay