public Type getType() { return qualifiedType.getType(); }
private static Object checkResult(Object result, QualifiedType<?> type) { if (result == null && getErasedType(type.getType()).isPrimitive()) { throw new IllegalStateException("SQL method returns primitive " + type + ", but statement returned no results"); } return result; }
private UnsupportedOperationException factoryNotFound(QualifiedType<?> qualifiedType, Object value) { Type type = qualifiedType.getType(); if (type instanceof Class<?>) { // not a ParameterizedType final TypeVariable<?>[] params = ((Class<?>) type).getTypeParameters(); if (params.length > 0) { return new UnsupportedOperationException("No type parameters found for erased type '" + type + Arrays.toString(params) + "' with qualifiers '" + qualifiedType.getQualifiers() + "'. To bind a generic type, prefer using bindByType."); } } return new UnsupportedOperationException("No argument factory registered for '" + value + "' of qualified type " + qualifiedType); }
@Override public Optional<ColumnMapper<?>> build(QualifiedType<?> givenType, ConfigRegistry config) { return Optional.of(givenType.getType()) .map(GenericTypes::getErasedType) .filter(Class::isEnum) .flatMap(clazz -> makeEnumArgument((QualifiedType<Enum>) givenType, (Class<Enum>) clazz, config)); }
@Override protected Object reducedResult(Stream<?> stream, StatementContext ctx) { Collector collector = ctx.findCollectorFor(returnType.getType()).orElse(null); if (collector != null) { return stream.collect(collector); } return checkResult(stream.findFirst().orElse(null), returnType); }
@Override @SuppressWarnings("unchecked") public Optional<Argument> build(QualifiedType<?> givenType, Object value, ConfigRegistry config) { return ifEnum(givenType.getType()) .flatMap(clazz -> makeEnumArgument((QualifiedType<Enum>) givenType, (Enum) value, config)); }
/** * Adapts a {@link ColumnMapperFactory} into a QualifiedColumnMapperFactory. The returned * factory only matches qualified types with zero qualifiers. * * @param factory the factory to adapt */ static QualifiedColumnMapperFactory adapt(ColumnMapperFactory factory) { Set<Annotation> qualifiers = getQualifiers(factory.getClass()); return (type, config) -> type.getQualifiers().equals(qualifiers) ? factory.build(type.getType(), config) : Optional.empty(); }
private static <T> Optional<EnumStrategy> doFindStrategy(QualifiedType<T> type) { boolean hasByName = type.hasQualifier(EnumByName.class); boolean hasByOrdinal = type.hasQualifier(EnumByOrdinal.class); if (hasByName && hasByOrdinal) { throw new IllegalArgumentException(String.format( "%s is both %s and %s", type.getType(), EnumByName.class.getSimpleName(), EnumByOrdinal.class.getSimpleName() )); } if (hasByName) { return Optional.of(EnumStrategy.BY_NAME); } else if (hasByOrdinal) { return Optional.of(EnumStrategy.BY_ORDINAL); } else { return Optional.empty(); } }
@Override @SuppressWarnings({ "unchecked", "rawtypes" }) protected Object mappedResult(ResultIterable<?> iterable, StatementContext ctx) { Collector collector = ctx.findCollectorFor(returnType.getType()).orElse(null); if (collector != null) { return iterable.collect(collector); } return checkResult(iterable.findFirst().orElse(null), returnType); }
/** * Adapts an {@link ArgumentFactory} into a QualifiedArgumentFactory. The returned factory only * matches qualified types with zero qualifiers. * * @param factory the factory to adapt */ static QualifiedArgumentFactory adapt(ArgumentFactory factory) { Set<Annotation> qualifiers = getQualifiers(factory.getClass()); return (type, value, config) -> type.getQualifiers().equals(qualifiers) ? factory.build(type.getType(), value, config) : Optional.empty(); } }
@Override protected BeanMapper<?> createNestedMapper(StatementContext ctx, PojoProperty<T> property, String nestedPrefix) { return new BeanMapper<>(GenericTypes.getErasedType(property.getQualifiedType().getType()), nestedPrefix); } }
/** * Obtain a mapper for the given qualified type. If the type is unqualified, * and a row mapper is registered for the given type, it is returned. If a * column mapper is registered for the given qualified type, it is adapted * into a row mapper, mapping the first column of the result set. If neither * a row or column mapper is registered, empty is returned. * * @param type the target qualified type to map to * @return a mapper for the given type, or empty if no row or column mapper * is registered for the given type. */ @Beta public <T> Optional<RowMapper<T>> findFor(QualifiedType<T> type) { if (type.getQualifiers().isEmpty()) { Optional<RowMapper<T>> result = rowMappers.findFor(type.getType()).map(m -> (RowMapper<T>) m); if (result.isPresent()) { return result; } } return columnMappers.findFor(type).map(SingleColumnMapper::new); }
@SuppressWarnings({ "rawtypes", "unchecked" }) // Type loses <T> protected PojoMapper<?> createNestedMapper(StatementContext ctx, PojoProperty<T> property, String nestedPrefix) { final Type propertyType = property.getQualifiedType().getType(); return new PojoMapper( GenericTypes.getErasedType(propertyType), ctx.getConfig(PojoTypes.class).findFor(type) .orElseThrow(() -> new UnableToProduceResultException("Couldn't find properties for nested type " + propertyType, ctx)), nestedPrefix); }
/** * Determines which strategy is to be used for a given {@link QualifiedType}, falling back to * reading strategy annotations on the source class and/or using the configured default. * * @param <E> the {@link Enum} type * @param type qualified type to derive a strategy from * @return the strategy by which this enum should be handled */ public <E extends Enum<E>> EnumStrategy findStrategy(QualifiedType<E> type) { Class<?> erasedType = getErasedType(type.getType()); return JdbiOptionals.findFirstPresent( () -> doFindStrategy(type), () -> doFindStrategy(QualifiedType.of(erasedType).with(getQualifiers(erasedType))) ).orElseGet(() -> registry.get(Enums.class).getDefaultStrategy()); }