Skip to content

Commit c722788

Browse files
mp911dechristophstrobl
authored andcommitted
Polishing.
Original Pull Request: #4885
1 parent 28ef92c commit c722788

File tree

12 files changed

+145
-129
lines changed

12 files changed

+145
-129
lines changed

Diff for: spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java

+28-24
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
import java.util.Map.Entry;
2525
import java.util.Optional;
2626
import java.util.function.Function;
27-
import java.util.stream.Collectors;
2827

2928
import org.bson.BsonBinary;
3029
import org.bson.BsonBinarySubType;
3130
import org.bson.BsonNull;
3231
import org.bson.Document;
32+
3333
import org.springframework.data.mongodb.core.mapping.Field;
3434
import org.springframework.data.mongodb.core.query.Collation;
3535
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty;
@@ -43,7 +43,6 @@
4343
import org.springframework.data.util.Optionals;
4444
import org.springframework.lang.CheckReturnValue;
4545
import org.springframework.lang.Contract;
46-
import org.springframework.lang.NonNull;
4746
import org.springframework.lang.Nullable;
4847
import org.springframework.util.Assert;
4948
import org.springframework.util.ObjectUtils;
@@ -241,11 +240,11 @@ public CollectionOptions collation(@Nullable Collation collation) {
241240
* Create new {@link CollectionOptions} with already given settings and {@code validationOptions} set to given
242241
* {@link MongoJsonSchema}.
243242
*
244-
* @param schema can be {@literal null}.
243+
* @param schema must not be {@literal null}.
245244
* @return new {@link CollectionOptions}.
246245
* @since 2.1
247246
*/
248-
public CollectionOptions schema(@Nullable MongoJsonSchema schema) {
247+
public CollectionOptions schema(MongoJsonSchema schema) {
249248
return validator(Validator.schema(schema));
250249
}
251250

@@ -473,7 +472,7 @@ public Optional<CollectionChangeStreamOptions> getChangeStreamOptions() {
473472
* Get the {@code encryptedFields} if available.
474473
*
475474
* @return {@link Optional#empty()} if not specified.
476-
* @since 4.5.0
475+
* @since 4.5
477476
*/
478477
public Optional<EncryptedFieldsOptions> getEncryptedFieldsOptions() {
479478
return Optional.ofNullable(encryptedFieldsOptions);
@@ -552,7 +551,8 @@ public static class ValidationOptions {
552551
private final @Nullable ValidationLevel validationLevel;
553552
private final @Nullable ValidationAction validationAction;
554553

555-
public ValidationOptions(Validator validator, ValidationLevel validationLevel, ValidationAction validationAction) {
554+
public ValidationOptions(@Nullable Validator validator, @Nullable ValidationLevel validationLevel,
555+
@Nullable ValidationAction validationAction) {
556556

557557
this.validator = validator;
558558
this.validationLevel = validationLevel;
@@ -669,16 +669,27 @@ public int hashCode() {
669669

670670
/**
671671
* Encapsulation of Encryption options for collections.
672-
*
672+
*
673673
* @author Christoph Strobl
674674
* @since 4.5
675675
*/
676676
public static class EncryptedFieldsOptions {
677677

678678
private static final EncryptedFieldsOptions NONE = new EncryptedFieldsOptions();
679679

680-
private @Nullable MongoJsonSchema schema;
681-
private List<QueryableJsonSchemaProperty> queryableProperties;
680+
private final @Nullable MongoJsonSchema schema;
681+
private final List<QueryableJsonSchemaProperty> queryableProperties;
682+
683+
EncryptedFieldsOptions() {
684+
this(null, List.of());
685+
}
686+
687+
private EncryptedFieldsOptions(@Nullable MongoJsonSchema schema,
688+
List<QueryableJsonSchemaProperty> queryableProperties) {
689+
690+
this.schema = schema;
691+
this.queryableProperties = queryableProperties;
692+
}
682693

683694
/**
684695
* @return {@link EncryptedFieldsOptions#NONE}
@@ -701,17 +712,6 @@ public static EncryptedFieldsOptions fromProperties(List<QueryableJsonSchemaProp
701712
return new EncryptedFieldsOptions(null, List.copyOf(properties));
702713
}
703714

704-
EncryptedFieldsOptions() {
705-
this(null, List.of());
706-
}
707-
708-
private EncryptedFieldsOptions(@Nullable MongoJsonSchema schema,
709-
List<QueryableJsonSchemaProperty> queryableProperties) {
710-
711-
this.schema = schema;
712-
this.queryableProperties = queryableProperties;
713-
}
714-
715715
/**
716716
* Add a new {@link QueryableJsonSchemaProperty queryable property} for the given source property.
717717
* <p>
@@ -739,7 +739,6 @@ public Document toDocument() {
739739
return new Document("fields", selectPaths());
740740
}
741741

742-
@NonNull
743742
private List<Document> selectPaths() {
744743

745744
Map<String, Document> fields = new LinkedHashMap<>();
@@ -760,10 +759,13 @@ private List<Document> fromProperties() {
760759

761760
List<Document> converted = new ArrayList<>(queryableProperties.size());
762761
for (QueryableJsonSchemaProperty property : queryableProperties) {
762+
763763
Document field = new Document("path", property.getIdentifier());
764+
764765
if (!property.getTypes().isEmpty()) {
765766
field.append("bsonType", property.getTypes().iterator().next().toBsonType().value());
766767
}
768+
767769
if (property
768770
.getTargetProperty() instanceof IdentifiableJsonSchemaProperty.EncryptedJsonSchemaProperty encrypted) {
769771
if (encrypted.getKeyId() != null) {
@@ -775,11 +777,13 @@ private List<Document> fromProperties() {
775777
}
776778
}
777779
}
778-
field.append("queries", property.getCharacteristics().getCharacteristics().stream()
779-
.map(QueryCharacteristic::toDocument).collect(Collectors.toList()));
780+
781+
field.append("queries", property.getCharacteristics().map(QueryCharacteristic::toDocument).toList());
782+
780783
if (!field.containsKey("keyId")) {
781784
field.append("keyId", BsonNull.VALUE);
782785
}
786+
783787
converted.add(field);
784788
}
785789
return converted;
@@ -813,7 +817,7 @@ private List<Document> fromSchema() {
813817
}
814818
}
815819

816-
private static void collectPaths(Document document, String currentPath, Map<String, Document> paths) {
820+
private static void collectPaths(Document document, @Nullable String currentPath, Map<String, Document> paths) {
817821

818822
if (document.containsKey("type") && document.get("type").equals("object")) {
819823
Object o = document.get("properties");

Diff for: spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java

+10-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Map;
2323
import java.util.Optional;
2424
import java.util.concurrent.TimeUnit;
25+
import java.util.function.Predicate;
2526

2627
import org.bson.BsonNull;
2728
import org.bson.Document;
@@ -377,14 +378,16 @@ public CreateCollectionOptions convertToCreateCollectionOptions(@Nullable Collec
377378
result.timeSeriesOptions(options);
378379
});
379380

380-
collectionOptions.getChangeStreamOptions().ifPresent(it -> result
381-
.changeStreamPreAndPostImagesOptions(new ChangeStreamPreAndPostImagesOptions(it.getPreAndPostImages())));
381+
collectionOptions.getChangeStreamOptions() //
382+
.map(CollectionOptions.CollectionChangeStreamOptions::getPreAndPostImages) //
383+
.map(ChangeStreamPreAndPostImagesOptions::new) //
384+
.ifPresent(result::changeStreamPreAndPostImagesOptions);
385+
386+
collectionOptions.getEncryptedFieldsOptions() //
387+
.map(EncryptedFieldsOptions::toDocument) //
388+
.filter(Predicate.not(Document::isEmpty)) //
389+
.ifPresent(result::encryptedFields);
382390

383-
collectionOptions.getEncryptedFieldsOptions().map(EncryptedFieldsOptions::toDocument).ifPresent(encryptedFields -> {
384-
if (!encryptedFields.isEmpty()) {
385-
result.encryptedFields(encryptedFields);
386-
}
387-
});
388391
return result;
389392
}
390393

Diff for: spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java

+24-21
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.stream.Collectors;
2525

2626
import org.bson.Document;
27+
2728
import org.springframework.data.mapping.PersistentProperty;
2829
import org.springframework.data.mapping.context.MappingContext;
2930
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -32,7 +33,6 @@
3233
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
3334
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
3435
import org.springframework.data.mongodb.core.mapping.Queryable;
35-
import org.springframework.data.mongodb.core.mapping.RangeEncrypted;
3636
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ArrayJsonSchemaProperty;
3737
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.EncryptedJsonSchemaProperty;
3838
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ObjectJsonSchemaProperty;
@@ -126,29 +126,31 @@ public MongoJsonSchema createSchemaFor(Class<?> type) {
126126
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(type);
127127
MongoJsonSchemaBuilder schemaBuilder = MongoJsonSchema.builder();
128128

129-
{
130-
Encrypted encrypted = entity.findAnnotation(Encrypted.class);
131-
if (encrypted != null) {
129+
Encrypted encrypted = entity.findAnnotation(Encrypted.class);
130+
if (encrypted != null) {
131+
schemaBuilder.encryptionMetadata(getEncryptionMetadata(entity, encrypted));
132+
}
132133

133-
Document encryptionMetadata = new Document();
134+
List<JsonSchemaProperty> schemaProperties = computePropertiesForEntity(Collections.emptyList(), entity);
135+
schemaBuilder.properties(schemaProperties.toArray(new JsonSchemaProperty[0]));
134136

135-
Collection<Object> encryptionKeyIds = entity.getEncryptionKeyIds();
136-
if (!CollectionUtils.isEmpty(encryptionKeyIds)) {
137-
encryptionMetadata.append("keyId", encryptionKeyIds);
138-
}
137+
return schemaBuilder.build();
138+
}
139139

140-
if (StringUtils.hasText(encrypted.algorithm())) {
141-
encryptionMetadata.append("algorithm", encrypted.algorithm());
142-
}
140+
private static Document getEncryptionMetadata(MongoPersistentEntity<?> entity, Encrypted encrypted) {
143141

144-
schemaBuilder.encryptionMetadata(encryptionMetadata);
145-
}
142+
Document encryptionMetadata = new Document();
143+
144+
Collection<Object> encryptionKeyIds = entity.getEncryptionKeyIds();
145+
if (!CollectionUtils.isEmpty(encryptionKeyIds)) {
146+
encryptionMetadata.append("keyId", encryptionKeyIds);
146147
}
147148

148-
List<JsonSchemaProperty> schemaProperties = computePropertiesForEntity(Collections.emptyList(), entity);
149-
schemaBuilder.properties(schemaProperties.toArray(new JsonSchemaProperty[0]));
149+
if (StringUtils.hasText(encrypted.algorithm())) {
150+
encryptionMetadata.append("algorithm", encrypted.algorithm());
151+
}
150152

151-
return schemaBuilder.build();
153+
return encryptionMetadata;
152154
}
153155

154156
private List<JsonSchemaProperty> computePropertiesForEntity(List<MongoPersistentProperty> path,
@@ -190,8 +192,8 @@ private JsonSchemaProperty computeSchemaForProperty(List<MongoPersistentProperty
190192
Class<?> rawTargetType = computeTargetType(property); // target type before conversion
191193
Class<?> targetType = converter.getTypeMapper().getWriteTargetTypeFor(rawTargetType); // conversion target type
192194

193-
194-
if ((rawTargetType.isPrimitive() || ClassUtils.isPrimitiveArray(rawTargetType)) && targetType == Object.class || ClassUtils.isAssignable(targetType, rawTargetType) ) {
195+
if ((rawTargetType.isPrimitive() || ClassUtils.isPrimitiveArray(rawTargetType)) && targetType == Object.class
196+
|| ClassUtils.isAssignable(targetType, rawTargetType)) {
195197
targetType = rawTargetType;
196198
}
197199

@@ -317,14 +319,15 @@ public Document toDocument() {
317319
if (queryable.contentionFactor() >= 0) {
318320
options.put("contention", queryable.contentionFactor());
319321
}
320-
if (!queryable.queryAttributes().isEmpty()) {
322+
323+
if (StringUtils.hasText(queryable.queryAttributes())) {
321324
options.putAll(Document.parse(queryable.queryAttributes()));
322325
}
323326

324327
return options;
325328
}
326329
};
327-
return new QueryableJsonSchemaProperty(enc, QueryCharacteristics.of(List.of(characteristic)));
330+
return new QueryableJsonSchemaProperty(enc, QueryCharacteristics.of(characteristic));
328331
}
329332

330333
private JsonSchemaProperty createObjectSchemaPropertyForEntity(List<MongoPersistentProperty> path,

Diff for: spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConversionContext.java

+10-29
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ public MongoPersistentProperty getProperty() {
7979
}
8080

8181
/**
82-
*
8382
* @param operatorContext
8483
* @return new instance of {@link MongoConversionContext}.
8584
* @since 4.5
@@ -119,71 +118,53 @@ public OperatorContext getOperatorContext() {
119118
/**
120119
* The {@link OperatorContext} provides access to the actual conversion intent like a write operation or a query
121120
* operator such as {@literal $gte}.
122-
*
121+
*
123122
* @since 4.5
124123
*/
125124
public interface OperatorContext {
126125

127126
/**
128127
* The operator the conversion is used in.
128+
*
129129
* @return {@literal write} for simple write operations during save, or a query operator.
130130
*/
131-
String getOperator();
131+
String operator();
132132

133133
/**
134134
* The context path the operator is used in.
135+
*
135136
* @return never {@literal null}.
136137
*/
137-
String getPath();
138+
String path();
138139

139140
boolean isWriteOperation();
140-
}
141-
142-
public static class WriteOperatorContext implements OperatorContext {
143141

144-
private final String path;
142+
}
145143

146-
public WriteOperatorContext(String path) {
147-
this.path = path;
148-
}
144+
record WriteOperatorContext(String path) implements OperatorContext {
149145

150146
@Override
151-
public String getOperator() {
147+
public String operator() {
152148
return "write";
153149
}
154150

155-
@Override
156-
public String getPath() {
157-
return path;
158-
}
159-
160151
@Override
161152
public boolean isWriteOperation() {
162153
return true;
163154
}
164155
}
165156

166-
public static class QueryOperatorContext implements OperatorContext {
167-
168-
private final String operator;
169-
private final String path;
157+
record QueryOperatorContext(String operator, String path) implements OperatorContext {
170158

171159
public QueryOperatorContext(@Nullable String operator, String path) {
172160
this.operator = operator != null ? operator : "$eq";
173161
this.path = path;
174162
}
175163

176-
public String getOperator() {
177-
return operator;
178-
}
179-
180-
public String getPath() {
181-
return path;
182-
}
183-
184164
@Override
185165
public boolean isWriteOperation() {
186166
return false;
187167
}
188168
}
169+
189170
}

Diff for: spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,8 @@ protected Object convertValueWithConversionContext(Field documentField, Object s
711711

712712
return BsonUtils.mapValues(document, (key, val) -> {
713713
if (isKeyword(key)) {
714-
return convertValueWithConversionContext(documentField, val, val, valueConverter, conversionContext.forOperator(new QueryOperatorContext(key, conversionContext.getOperatorContext().getPath())));
714+
return convertValueWithConversionContext(documentField, val, val, valueConverter, conversionContext
715+
.forOperator(new QueryOperatorContext(key, conversionContext.getOperatorContext().path())));
715716
}
716717
return val;
717718
});

0 commit comments

Comments
 (0)