Polishing.
Reformat code. Tweak documentation wording. See #3596 Original pull request: #3982.
This commit is contained in:
@@ -176,8 +176,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Assert.notNull(path, "ObjectPath must not be null");
|
||||
|
||||
return new ConversionContext(this, conversions, path, this::readDocument, this::readCollectionOrArray, this::readMap,
|
||||
this::readDBRef, this::getPotentiallyConvertedSimpleRead);
|
||||
return new ConversionContext(this, conversions, path, this::readDocument, this::readCollectionOrArray,
|
||||
this::readMap, this::readDBRef, this::getPotentiallyConvertedSimpleRead);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,18 +393,18 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
EntityProjection<?, ?> property = returnedTypeDescriptor.findProperty(name);
|
||||
if (property == null) {
|
||||
return new ConversionContext(conversions, path, MappingMongoConverter.this::readDocument, collectionConverter,
|
||||
return new ConversionContext(sourceConverter, conversions, path, MappingMongoConverter.this::readDocument, collectionConverter,
|
||||
mapConverter, dbRefConverter, elementConverter);
|
||||
}
|
||||
|
||||
return new ProjectingConversionContext(sourceConverter, conversions, path, collectionConverter, mapConverter, dbRefConverter,
|
||||
elementConverter, property);
|
||||
return new ProjectingConversionContext(sourceConverter, conversions, path, collectionConverter, mapConverter,
|
||||
dbRefConverter, elementConverter, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionContext withPath(ObjectPath currentPath) {
|
||||
return new ProjectingConversionContext(sourceConverter, conversions, currentPath, collectionConverter, mapConverter,
|
||||
dbRefConverter, elementConverter, returnedTypeDescriptor);
|
||||
return new ProjectingConversionContext(sourceConverter, conversions, currentPath, collectionConverter,
|
||||
mapConverter, dbRefConverter, elementConverter, returnedTypeDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,8 +935,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if(conversions.hasPropertyValueConverter(prop)) {
|
||||
accessor.put(prop, conversions.getPropertyValueConverter(prop).write(obj, new MongoConversionContext(prop, this)));
|
||||
if (conversions.hasPropertyValueConverter(prop)) {
|
||||
accessor.put(prop,
|
||||
conversions.getPropertyValueConverter(prop).write(obj, new MongoConversionContext(prop, this)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1270,8 +1271,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property) {
|
||||
DocumentAccessor accessor = new DocumentAccessor(bson);
|
||||
|
||||
if(conversions.hasPropertyValueConverter(property)) {
|
||||
accessor.put(property, conversions.getPropertyValueConverter(property).write(value, new MongoConversionContext(property, this)));
|
||||
if (conversions.hasPropertyValueConverter(property)) {
|
||||
accessor.put(property,
|
||||
conversions.getPropertyValueConverter(property).write(value, new MongoConversionContext(property, this)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1916,9 +1918,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
if(context.conversions.hasPropertyValueConverter(property)) {
|
||||
|
||||
return (T) context.conversions.getPropertyValueConverter(property).read(value, new MongoConversionContext(property, context.sourceConverter));
|
||||
if (context.conversions.hasPropertyValueConverter(property)) {
|
||||
return (T) context.conversions.getPropertyValueConverter(property).read(value,
|
||||
new MongoConversionContext(property, context.sourceConverter));
|
||||
}
|
||||
|
||||
return (T) context.convert(value, property.getTypeInformation());
|
||||
@@ -2148,7 +2150,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
final ContainerValueConverter<DBRef> dbRefConverter;
|
||||
final ValueConverter<Object> elementConverter;
|
||||
|
||||
ConversionContext(MongoConverter sourceConverter, org.springframework.data.convert.CustomConversions customConversions, ObjectPath path,
|
||||
ConversionContext(MongoConverter sourceConverter,
|
||||
org.springframework.data.convert.CustomConversions customConversions, ObjectPath path,
|
||||
ContainerValueConverter<Bson> documentConverter, ContainerValueConverter<Collection<?>> collectionConverter,
|
||||
ContainerValueConverter<Bson> mapConverter, ContainerValueConverter<DBRef> dbRefConverter,
|
||||
ValueConverter<Object> elementConverter) {
|
||||
@@ -2235,8 +2238,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Assert.notNull(currentPath, "ObjectPath must not be null");
|
||||
|
||||
return new ConversionContext(sourceConverter, conversions, currentPath, documentConverter, collectionConverter, mapConverter,
|
||||
dbRefConverter, elementConverter);
|
||||
return new ConversionContext(sourceConverter, conversions, currentPath, documentConverter, collectionConverter,
|
||||
mapConverter, dbRefConverter, elementConverter);
|
||||
}
|
||||
|
||||
public ObjectPath getPath() {
|
||||
|
||||
@@ -50,11 +50,7 @@ public class MongoConversionContext implements ValueConversionContext<MongoPersi
|
||||
|
||||
@Override
|
||||
public <T> T read(@Nullable Object value, TypeInformation<T> target) {
|
||||
|
||||
if (!(value instanceof Bson)) {
|
||||
return ValueConversionContext.super.read(value, target);
|
||||
}
|
||||
|
||||
return mongoConverter.read(target.getType(), (Bson) value);
|
||||
return value instanceof Bson ? mongoConverter.read(target.getType(), (Bson) value)
|
||||
: ValueConversionContext.super.read(value, target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.data.convert.ConverterBuilder;
|
||||
import org.springframework.data.convert.PropertyValueConversions;
|
||||
import org.springframework.data.convert.PropertyValueConverter;
|
||||
import org.springframework.data.convert.PropertyValueConverterFactory;
|
||||
@@ -263,7 +264,8 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@link Converter converters}, {@link ConverterFactory factories}, ...
|
||||
* Add {@link Converter converters}, {@link ConverterFactory factories}, {@link ConverterBuilder.ConverterAware
|
||||
* converter-aware objects}, and {@link GenericConverter generic converters}.
|
||||
*
|
||||
* @param converters must not be {@literal null} nor contain {@literal null} values.
|
||||
* @return this.
|
||||
@@ -307,6 +309,7 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
*/
|
||||
public MongoConverterConfigurationAdapter setPropertyValueConversions(PropertyValueConversions valueConversions) {
|
||||
|
||||
Assert.notNull(valueConversions, "PropertyValueConversions must not be null");
|
||||
this.propertyValueConversions = valueConversions;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import org.springframework.data.convert.PropertyValueConverter;
|
||||
|
||||
/**
|
||||
* Pre typed {@link PropertyValueConverter} specific for the Data MongoDB module.
|
||||
*
|
||||
* MongoDB-specific {@link PropertyValueConverter} extension.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 3.4
|
||||
*/
|
||||
public interface MongoValueConverter<S, T> extends PropertyValueConverter<S, T, MongoConversionContext> {
|
||||
|
||||
}
|
||||
public interface MongoValueConverter<S, T> extends PropertyValueConverter<S, T, MongoConversionContext> {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
== What's New in Spring Data MongoDB 3.4
|
||||
|
||||
* Find and update ``Document``s via <<mongodb.repositories.queries.update,Repository method>>.
|
||||
* Property specific <<mongo.property-converters, value converters>>.
|
||||
* Property-specific <<mongo.property-converters, value converters>>.
|
||||
|
||||
[[new-features.3.3]]
|
||||
== What's New in Spring Data MongoDB 3.3
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[[mongo.property-converters]]
|
||||
== Property Converters - Mapping specific fields
|
||||
|
||||
Although to the <<mongo.custom-converters, type based conversion>> already offers means to influence the representation of certain types within the target store it has its limitations when not all potential values of that type should be considered as a conversion targets.
|
||||
Property based converters allow to specify conversion instructions on a per property basis either declarative, via `@ValueConverter`, or programmatic by registering a `PropertyValueConverter` for a specific field.
|
||||
While <<mongo.custom-converters, type-based conversion>> already offers ways to influence the conversion and representation of certain types within the target store it has its limitations when only certain values or properties of a particular type should be considered for conversion.
|
||||
Property-based converters allow configuring conversion rules on a per-property basis, either declarative, via `@ValueConverter`, or programmatic by registering a `PropertyValueConverter` for a specific property.
|
||||
|
||||
A `PropertyValueConverter` is responsible of transforming a given value into its store representation (write) and back (read) as shown in the snippet below.
|
||||
Please mind the presence of the `ValueConversionContext` providing additional information, such as mapping metadata.
|
||||
A `PropertyValueConverter` can transform a given value into its store representation (**write**) and back (**read**) as shown in the snippet below.
|
||||
The additional `ValueConversionContext` provides additional information, such as mapping metadata and direct `read`/`write` methods.
|
||||
|
||||
.PropertyValueConverter
|
||||
.A simple PropertyValueConverter
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@@ -26,69 +26,75 @@ class ReversingValueConverter implements PropertyValueConverter<String, String,
|
||||
----
|
||||
====
|
||||
|
||||
`PropertyValueConverter` instances can be obtained via `CustomConversions#getPropertyValueConverter(...)` delegating to `PropertyValueConversions` typically using a `PropertyValueConverterFactory` to provide the actual converter.
|
||||
Depending on the applications needs multiple instances of `PropertyValueConverterFactory` can be chained or decorated (eg. for caching).
|
||||
By default a caching implementation is used that is capable of serving types with a default constructor or enum values.
|
||||
A set of predefined factories is available via `PropertyValueConverterFactory`.
|
||||
To obtain a `PropertyValueConverter` from an `ApplicationContext` make sure to use the `PropertyValueConverterFactory.beanFactoryAware(...)` factory.
|
||||
`PropertyValueConverter` instances can be obtained via `CustomConversions#getPropertyValueConverter(…)` delegating to `PropertyValueConversions`, typically using a `PropertyValueConverterFactory` providing the actual converter.
|
||||
Depending on the applications needs, multiple instances of `PropertyValueConverterFactory` can be chained or decorated, for example to apply caching.
|
||||
By default, a caching implementation is used that is capable of serving types with a default constructor or enum values.
|
||||
A set of predefined factories is available through `PropertyValueConverterFactory` factory methods.
|
||||
Use `PropertyValueConverterFactory.beanFactoryAware(…)` to obtain a `PropertyValueConverter` instances from an `ApplicationContext`.
|
||||
|
||||
Changing the default behavior can be done via the `ConverterConfiguration`.
|
||||
You can change the default behavior through `ConverterConfiguration`.
|
||||
|
||||
[[mongo.property-converters.declarative]]
|
||||
=== Declarative Value Converter
|
||||
|
||||
The most straight forward usage of a `PropertyValueConverter` is via the `@ValueConverter` annotation referring to the target converter type.
|
||||
The most straight forward usage of a `PropertyValueConverter` is by annotating properties with the `@ValueConverter` annotation that defines the converter type.
|
||||
|
||||
.Declarative PropertyValueConverter
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public class Person {
|
||||
// ...
|
||||
class Person {
|
||||
|
||||
@ValueConverter(ReversingValueConverter.class)
|
||||
String ssn;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
=== Programmatic Value Converter
|
||||
[[mongo.property-converters.programmatic]]
|
||||
=== Programmatic Value Converter Registration
|
||||
|
||||
Following the programmatic approach does not require to put additional annotations on the domain model but registers `PropertyValueConverter` instances for certain paths in a `PropertyValueConverterRegistrar` as shown below.
|
||||
Programmatic registration registers `PropertyValueConverter` instances for properties within an entity model using a `PropertyValueConverterRegistrar` as shown below.
|
||||
The difference to declarative registration is that programmatic registration happens entirely outside of the entity model.
|
||||
Such an approach is useful if you cannot or do not want to annotate the entity model.
|
||||
|
||||
.Programmatic PropertyValueConverter
|
||||
.Programmatic PropertyValueConverter registration
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
PropertyValueConverterRegistrar registrar = new PropertyValueConverterRegistrar();
|
||||
|
||||
registrar.registerConverter(Address.class, "street", new PropertyValueConverter() { ... }); <1>
|
||||
registrar.registerConverter(Address.class, "street", new PropertyValueConverter() { … }); <1>
|
||||
|
||||
// type safe registration
|
||||
registrar.registerConverter(Person.class, Person::getSsn()) <2>
|
||||
registrar.registerConverter(Person.class, Person::getSsn()) <2>
|
||||
.writing(value -> encrypt(value))
|
||||
.reading(value -> decrypt(value));
|
||||
----
|
||||
|
||||
<1> Register a converter for the field identified by its name.
|
||||
<2> Type safe variant that allows to register a converter and its conversion functions.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Dot notation (eg. `registerConverter(Person.class, "address.street", ...)`) is *not* supported when registering converters.
|
||||
Dot-notation (such as `registerConverter(Person.class, "address.street", …)`) nagivating across properties into subdocuments is *not* supported when registering converters.
|
||||
====
|
||||
|
||||
[[mongo.property-converters.value-conversions]]
|
||||
=== MongoDB property value conversions
|
||||
|
||||
The above sections outlined the purpose an overall structure of `PropertyValueConverters`.
|
||||
This section will focus on MongoDB specific aspects.
|
||||
|
||||
==== MongoValueConverter & MongoConversionContext
|
||||
==== MongoValueConverter and MongoConversionContext
|
||||
|
||||
The `MongoValueConverter` offers a pre typed `PropertyValueConverter` interface leveraging the `MongoConversionContext`.
|
||||
`MongoValueConverter` offers a pre typed `PropertyValueConverter` interface leveraging the `MongoConversionContext`.
|
||||
|
||||
==== MongoCustomConversions configuration
|
||||
|
||||
`MongoCustomConversions` are by default capable of dealing with declarative value converters depending on the configured `PropertyValueConverterFactory`.
|
||||
The `MongoConverterConfigurationAdapter` is there to help set up programmatic value conversions or define the `PropertyValueConverterFactory` to be used.
|
||||
`MongoCustomConversions` are by default capable of handling declarative value converters depending on the configured `PropertyValueConverterFactory`.
|
||||
`MongoConverterConfigurationAdapter` is there to help set up programmatic value conversions or define the `PropertyValueConverterFactory` to be used.
|
||||
|
||||
.Configuration Sample
|
||||
====
|
||||
@@ -97,10 +103,10 @@ The `MongoConverterConfigurationAdapter` is there to help set up programmatic va
|
||||
MongoCustomConversions.create(configurationAdapter -> {
|
||||
|
||||
SimplePropertyValueConversions valueConversions = new SimplePropertyValueConversions();
|
||||
valueConversions.setConverterFactory(...);
|
||||
valueConversions.setConverterFactory(…);
|
||||
valueConversions.setValueConverterRegistry(new PropertyValueConverterRegistrar()
|
||||
.registerConverter(...)
|
||||
.buildRegistry());
|
||||
.registerConverter(…)
|
||||
.buildRegistry());
|
||||
|
||||
configurationAdapter.setPropertyValueConversions(valueConversions);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user