diff --git a/pom.xml b/pom.xml index 7cb1d10f85..5084456997 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-GH-3766-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 0033bd11d5..2526cfee1a 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-GH-3766-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f62c8dc7f4..f40807f457 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-GH-3766-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 2f73c10eba..c2dfc33d1e 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-GH-3766-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java index a53ff8f5a5..06033347ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java @@ -27,11 +27,11 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.convert.MongoConverter; -import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.Encrypted; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ArrayJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.EncryptedJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ObjectJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.JsonSchemaObject; @@ -160,15 +160,15 @@ private JsonSchemaProperty computeSchemaForProperty(List rawTargetType = computeTargetType(property); // target type before conversion Class targetType = converter.getTypeMapper().getWriteTargetTypeFor(rawTargetType); // conversion target type - if (property.isEntity() && ObjectUtils.nullSafeEquals(rawTargetType, targetType)) { + if (!isCollection(property) && property.isEntity() && ObjectUtils.nullSafeEquals(rawTargetType, targetType)) { return createObjectSchemaPropertyForEntity(path, property, required); } String fieldName = computePropertyFieldName(property); JsonSchemaProperty schemaProperty; - if (property.isCollectionLike()) { - schemaProperty = createSchemaProperty(fieldName, targetType, required); + if (isCollection(property)) { + schemaProperty = createSchemaPropertyForCollection(fieldName, property, required); } else if (property.isMap()) { schemaProperty = createSchemaProperty(fieldName, Type.objectType(), required); } else if (ClassUtils.isAssignable(Enum.class, targetType)) { @@ -180,6 +180,48 @@ private JsonSchemaProperty computeSchemaForProperty(List persistentEntity = mappingContext + .getPersistentEntity(property.getTypeInformation().getComponentType()); + + if (persistentEntity == null) { + + if (ClassUtils.isAssignable(Enum.class, property.getActualType())) { + + List possibleValues = new ArrayList<>(); + + for (Object enumValue : EnumSet.allOf((Class) property.getActualType())) { + possibleValues.add(converter.convertToMongoType(enumValue)); + } + + Class targetType = possibleValues.isEmpty() ? property.getActualType() + : possibleValues.iterator().next().getClass(); + schemaProperty = schemaProperty + .items(Collections.singleton(JsonSchemaObject.of(targetType).possibleValues(possibleValues))); + } else { + schemaProperty = schemaProperty.items(Collections.singleton(JsonSchemaObject.of(property.getActualType()))); + } + } else { + + List nestedProperties = computePropertiesForEntity(Collections.emptyList(), + persistentEntity); + + if (!nestedProperties.isEmpty()) { + schemaProperty = schemaProperty.items(Collections + .singleton(JsonSchemaObject.object().properties(nestedProperties.toArray(new JsonSchemaProperty[0])))); + } + } + } + + return createPotentiallyRequiredSchemaProperty(schemaProperty, required); + } + @Nullable private JsonSchemaProperty applyEncryptionDataIfNecessary(MongoPersistentProperty property, JsonSchemaProperty schemaProperty) { @@ -197,7 +239,6 @@ private JsonSchemaProperty applyEncryptionDataIfNecessary(MongoPersistentPropert enc = enc.keys(property.getEncryptionKeyIds()); } return enc; - } private JsonSchemaProperty createObjectSchemaPropertyForEntity(List path, @@ -268,6 +309,10 @@ private Class computeTargetType(PersistentProperty property) { return mongoProperty.getFieldType() != mongoProperty.getActualType() ? Object.class : mongoProperty.getFieldType(); } + private static boolean isCollection(MongoPersistentProperty property) { + return property.isCollectionLike() && !property.getType().equals(byte[].class); + } + static JsonSchemaProperty createPotentiallyRequiredSchemaProperty(JsonSchemaProperty property, boolean required) { if (!required) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java index 9fd19189ce..797021cb8f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java @@ -185,6 +185,9 @@ enum JustSomeEnum { " 'arrayProperty' : { 'type' : 'array' }," + // " 'binaryDataProperty' : { 'bsonType' : 'binData' }," + // " 'collectionProperty' : { 'type' : 'array' }," + // + " 'simpleTypeCollectionProperty' : { 'type' : 'array', 'items' : { 'type' : 'string' } }," + // + " 'complexTypeCollectionProperty' : { 'type' : 'array', 'items' : { 'type' : 'object', 'properties' : { 'field' : { 'type' : 'string'} } } }" + // + " 'enumTypeCollectionProperty' : { 'type' : 'array', 'items' : " + JUST_SOME_ENUM + " }" + // " 'mapProperty' : { 'type' : 'object' }," + // " 'objectProperty' : { 'type' : 'object' }," + // " 'enumProperty' : " + JUST_SOME_ENUM + " }" + // @@ -203,12 +206,19 @@ static class VariousFieldTypes { Date dateProperty; Object[] arrayProperty; byte[] binaryDataProperty; - List collectionProperty; + List collectionProperty; + List simpleTypeCollectionProperty; + List complexTypeCollectionProperty; + List enumTypeCollectionProperty; Map mapProperty; Object objectProperty; JustSomeEnum enumProperty; } + static class SomeDomainType { + String field; + } + // --> NESTED DOMAIN TYPE static final String WITH_NESTED_DOMAIN_TYPE = "" + //