/* See LICENSE for licensing and NOTICE for copyright. */ package org.ldaptive.beans.spring; import java.time.ZonedDateTime; import org.ldaptive.beans.AbstractLdapEntryMapper; import org.ldaptive.beans.ClassDescriptor; import org.ldaptive.beans.spring.convert.StringToZonedDateTimeConverter; import org.ldaptive.beans.spring.convert.ZonedDateTimeToStringConverter; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.expression.EvaluationContext; import org.springframework.expression.TypeConverter; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardTypeConverter; /** * Uses a {@link SpringClassDescriptor} for ldap entry mapping. * * @param <T> type of object to map * * @author Middleware Services */ public class SpringLdapEntryMapper<T> extends AbstractLdapEntryMapper<T> { /** Type converter used by all contexts. */ private final TypeConverter typeConverter; /** Default constructor. */ public SpringLdapEntryMapper() { this((Converter<?, ?>) null); } /** * Creates a new spring ldap entry mapper. * * @param c additional converters to add to the spring conversion service. */ public SpringLdapEntryMapper(final Converter<?, ?>... c) { typeConverter = createTypeConverter(c); } @Override protected ClassDescriptor getClassDescriptor(final Object object) { final SpringClassDescriptor descriptor = new SpringClassDescriptor(createEvaluationContext(object)); descriptor.initialize(object.getClass()); return descriptor; } /** * Creates an evaluation context to use in the spring class descriptor. Adds the default converters from the default * conversion service. * * @param object to supply to the evaluation context * * @return evalutation context */ protected EvaluationContext createEvaluationContext(final Object object) { final StandardEvaluationContext context = new StandardEvaluationContext(object); context.setTypeConverter(typeConverter); return context; } /** * Returns a type converter that is initialized with the supplied converters and any converters supplied by {@link * #addDefaultConverters(GenericConversionService)}. * * @param converters to add to the conversion service * * @return type converter */ protected TypeConverter createTypeConverter(final Converter<?, ?>... converters) { final GenericConversionService conversionService = new GenericConversionService(); DefaultConversionService.addDefaultConverters(conversionService); if (converters != null) { for (Converter<?, ?> converter : converters) { if (converter != null) { conversionService.addConverter(converter); } } } addDefaultConverters(conversionService); return new StandardTypeConverter(conversionService); } /** * Adds default converters to the supplied conversion service. * * @param service to add default converters to */ protected void addDefaultConverters(final GenericConversionService service) { if (!service.canConvert(String.class, ZonedDateTime.class)) { service.addConverter(new StringToZonedDateTimeConverter()); } if (!service.canConvert(ZonedDateTime.class, String.class)) { service.addConverter(new ZonedDateTimeToStringConverter()); } } }