package org.simpleflatmapper.jooq; import org.jooq.*; import org.simpleflatmapper.map.Mapper; import org.simpleflatmapper.map.MapperConfig; import org.simpleflatmapper.map.property.FieldMapperColumnDefinition; import org.simpleflatmapper.reflect.ReflectionService; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Integration point with jooq.<p> * Provide a JooqRecordMapper backed by an Sfm {@link org.jooq.Record} {@link Mapper} */ public class SfmRecordMapperProvider implements RecordMapperProvider { private final ConcurrentMap<TargetColumnsMapperKey, Mapper<Record, ?>> mapperCache = new ConcurrentHashMap<TargetColumnsMapperKey, Mapper<Record, ?>>(); private final MapperConfig<JooqFieldKey, FieldMapperColumnDefinition<JooqFieldKey>> mapperConfig; private final ReflectionService reflectionService; public SfmRecordMapperProvider() { this(MapperConfig.<JooqFieldKey>fieldMapperConfig(), ReflectionService.newInstance()); } public SfmRecordMapperProvider( MapperConfig<JooqFieldKey, FieldMapperColumnDefinition<JooqFieldKey>> mapperConfig, ReflectionService reflectionService) { this.mapperConfig = mapperConfig; this.reflectionService = reflectionService; } @Override public <R extends Record, E> RecordMapper<R, E> provide(RecordType<R> recordType, Class<? extends E> type) { TargetColumnsMapperKey key = getMapperKey(recordType, type); @SuppressWarnings("unchecked") Mapper<Record, E> mapper = (Mapper<Record, E>) mapperCache.get(key); if (mapper == null) { mapper = buildMapper(recordType, type); mapperCache.putIfAbsent(key, mapper); } return new JooqRecordMapperWrapper<R, E>(mapper); } private <R extends Record, E> Mapper<Record, E> buildMapper(RecordType<R> recordType, Class<? extends E> type) { JooqMapperBuilder<E> mapperBuilder = new JooqMapperBuilder<E>( reflectionService.<E>getClassMeta(type), new JooqMappingContextFactoryBuilder<Record>(), mapperConfig); int i = 0; for(Field<?> field : recordType.fields()) { mapperBuilder.addField(new JooqFieldKey(field, i++)); } return mapperBuilder.mapper(); } private <R extends Record> TargetColumnsMapperKey getMapperKey(RecordType<R> recordType, Class<?> type) { String[] columns = new String[recordType.size()]; int i = 0; for(Field<?> field : recordType.fields()) { columns[i++] = field.getName(); } return new TargetColumnsMapperKey(type, columns); } }