All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.data.convert.PropertyValueConverterRegistrar Maven / Gradle / Ivy

There is a newer version: 3.4.0
Show newest version
/*
 * Copyright 2022-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.convert;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

import org.springframework.data.convert.PropertyValueConverter.FunctionPropertyValueConverter;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.MethodInvocationRecorder;
import org.springframework.util.Assert;

/**
 * Configuration class used to register a {@link PropertyValueConverter} with
 * a {@link SimplePropertyValueConverterRegistry} that can be used in {@link PropertyValueConversions}.
 * 

* It is possible to register type safe converters via {@link #registerConverter(Class, Function)} * *

 * registrar.registerConverter(Person.class, Person::getName) //
 * 		.writing(StringConverter::encrypt) //
 * 		.reading(StringConverter::decrypt);
 * 
* * @author Christoph Strobl * @author Oliver Drotbohm * @since 2.7 */ public class PropertyValueConverterRegistrar

> { private final SimplePropertyValueConverterRegistry

registry = new SimplePropertyValueConverterRegistry<>(); /** * Starts a converter registration by pointing to a property of a domain type. * * @param the domain type * @param the property type * @param type the domain type to obtain the property from * @param property a {@link Function} to describe the property to be referenced. * Usually a method handle to a getter. * @return will never be {@literal null}. */ public WritingConverterRegistrationBuilder registerConverter(Class type, Function property) { String propertyName = MethodInvocationRecorder.forProxyOf(type).record(property).getPropertyPath() .orElseThrow(() -> new IllegalArgumentException("Cannot obtain property name")); return new WritingConverterRegistrationBuilder<>(type, propertyName, this); } /** * Starts a converter registration by pointing to a property of a domain type. * * @param the domain type * @param the property type * @param type the domain type to obtain the property from * @param propertyName a {@link Function} to describe the property to be referenced. * Usually a method handle to a getter. * @return will never be {@literal null}. */ public WritingConverterRegistrationBuilder registerConverter(Class type, String propertyName, @SuppressWarnings("unused") Class propertyType) { return new WritingConverterRegistrationBuilder<>(type, propertyName, this); } /** * Register the given {@link PropertyValueConverter converter} for the given type and property identified by * its name. * * @param type the domain type to obtain the property from * @param path the property name. * @param converter the {@link PropertyValueConverter converter} to apply. * @return this. */ public PropertyValueConverterRegistrar

registerConverter(Class type, String path, PropertyValueConverter> converter) { registry.registerConverter(type, path, (PropertyValueConverter>) converter); return this; } /** * Register collected {@link PropertyValueConverter converters} within the given * {@link ValueConverterRegistry registry}. * * @param target {@link ValueConverterRegistry} from which to register {@link PropertyValueConverter converters}; * must not be {@literal null}. * @throws IllegalArgumentException if the {@link ValueConverterRegistry} is {@literal null}. * @see ValueConverterRegistry */ public void registerConvertersIn(ValueConverterRegistry

target) { Assert.notNull(target, "Target registry must not be null"); registry.getConverterRegistrationMap().forEach((key, value) -> target.registerConverter(key.type, key.path, value)); } /** * Obtain the {@link SimplePropertyValueConverterRegistry}. * * @return new instance of {@link SimplePropertyValueConverterRegistry}. */ public ValueConverterRegistry

buildRegistry() { return new SimplePropertyValueConverterRegistry<>(registry); } /** * Helper class used to build up a fluent registration API starting with writing. * * @author Oliver Drotbohm */ public static class WritingConverterRegistrationBuilder> { private final Consumer>> registration; private final PropertyValueConverterRegistrar

config; WritingConverterRegistrationBuilder(Class type, String property, PropertyValueConverterRegistrar

config) { this.config = config; this.registration = converter -> config.registerConverter(type, property, converter); } public ReadingConverterRegistrationBuilder writingAsIs() { return writing((source, context) -> source); } public ReadingConverterRegistrationBuilder writing(Function writer) { return writing((source, context) -> writer.apply(source)); } /** * Describes how to convert the domain property value into the database native property. * * @param the type to be written to the database * @param writer the property conversion to extract a value written to the database * @return will never be {@literal null}. */ public ReadingConverterRegistrationBuilder writing( BiFunction, R> writer) { return new ReadingConverterRegistrationBuilder<>(this, writer); } } /** * Helper class used to build a fluent API to register how to read a database value into a domain object property. * * @author Oliver Drotbohm */ public static class ReadingConverterRegistrationBuilder> { private final WritingConverterRegistrationBuilder origin; private final BiFunction, R> writer; ReadingConverterRegistrationBuilder(WritingConverterRegistrationBuilder origin, BiFunction, R> writer) { this.origin = origin; this.writer = writer; } @SuppressWarnings("unchecked") public PropertyValueConverterRegistrar

readingAsIs() { return reading((source, context) -> (S) source); } public PropertyValueConverterRegistrar

reading(Function reader) { return reading((source, context) -> reader.apply(source)); } /** * Describes how to read a database value into a domain object's property value. * * @param reader must not be {@literal null}. * @return the confiured {@link PropertyValueConverterRegistrar}. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public PropertyValueConverterRegistrar

reading(BiFunction, S> reader) { origin.registration.accept(new FunctionPropertyValueConverter(writer, reader)); return origin.config; } } }