/** * Obtain a column mapper for the given type. * * @param <T> the type to map * @param type the target type to map to * @return a ColumnMapper for the given type, or empty if no column mapper is registered for the given type. */ @SuppressWarnings("unchecked") public <T> Optional<ColumnMapper<T>> findFor(GenericType<T> type) { ColumnMapper<T> mapper = (ColumnMapper<T>) findFor(type.getType()).orElse(null); return Optional.ofNullable(mapper); }
/** * Use a column mapper to extract a type from the current ResultSet row. * @param <T> the type to map * @param column the column index * @param type the GenericType of the type * @return the materialized T */ @SuppressWarnings("unchecked") public <T> T getColumn(int column, GenericType<T> type) { return (T) getColumn(column, type.getType()); }
/** * Creates a {@code QualifiedType<T>} for a {@code GenericType<T>} with no qualifiers. * @param type the unqualified type * @return the unqualified QualifiedType * @see #with(Annotation...) to then qualify your type */ @SuppressWarnings("unchecked") public static <T> QualifiedType<T> of(GenericType<T> type) { return (QualifiedType<T>) of(type.getType()); }
/** * Use a column mapper to extract a type from the current ResultSet row. * @param <T> the type to map * @param column the column name * @param type the GenericType of the type * @return the materialized T */ @SuppressWarnings("unchecked") public <T> T getColumn(String column, GenericType<T> type) { return (T) getColumn(column, type.getType()); }
/** * Bind an argument dynamically by the generic type passed in. * * @param name token name to bind the parameter to * @param value to bind * @param argumentType type token for value argument * * @return the same Query instance */ public final This bindByType(String name, Object value, GenericType<?> argumentType) { return bindByType(name, value, argumentType.getType()); }
/** * Obtain a row mapper for the given type in the given context. * * @param <T> the type of the mapper to find * @param type the target type to map to * @return a RowMapper for the given type, or empty if no row mapper is registered for the given type. */ @SuppressWarnings("unchecked") public <T> Optional<RowMapper<T>> findFor(GenericType<T> type) { RowMapper<T> mapper = (RowMapper<T>) findFor(type.getType()).orElse(null); return Optional.ofNullable(mapper); }
/** * Use a row mapper to extract a type from the current ResultSet row. * @param <T> the type to map * @param rowType the GenericType of the type * @return the materialized T */ @SuppressWarnings("unchecked") public <T> T getRow(GenericType<T> rowType) { return (T) getRow(rowType.getType()); }
/** * Bind an argument dynamically by the generic type passed in. * * @param position position to bind the parameter at, starting at 0 * @param value to bind * @param argumentType type token for value argument * * @return the same Query instance */ public final This bindByType(int position, Object value, GenericType<?> argumentType) { return bindByType(position, value, argumentType.getType()); }
@SuppressWarnings("unchecked") <T> RowMapper<T> mapperForType(GenericType<T> type) { return (RowMapper<T>) mapperForType(type.getType()); }
/** * Obtain a mapper for the given type. If a row mapper is registered for the * given type, it is returned. If a column mapper is registered for the * given 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 <T> the type of the mapper to find * @param type the target 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. */ @SuppressWarnings("unchecked") public <T> Optional<RowMapper<T>> findFor(GenericType<T> type) { RowMapper<T> mapper = (RowMapper<T>) findFor(type.getType()).orElse(null); return Optional.ofNullable(mapper); }
/** * Register a column mapper for a given explicit {@link GenericType} * Column mappers may be reused by {@link RowMapper} to map individual columns. * * @param <T> the type * @param type the generic type to match with equals. * @param mapper the column mapper * @return this */ public <T> ColumnMappers register(GenericType<T> type, ColumnMapper<T> mapper) { return this.register(ColumnMapperFactory.of(type.getType(), mapper)); }
/** * Register a row mapper for a given type. * * @param <T> the type * @param type the type to match with equals. * @param mapper the row mapper * @return this */ public <T> RowMappers register(GenericType<T> type, RowMapper<T> mapper) { return this.register(RowMapperFactory.of(type.getType(), mapper)); }
private void testProjectionMapper(GenericType<? extends Tuple> projection, Tuple expected) throws SQLException { Optional<RowMapper<?>> mapper = unit.build(projection.getType(), null); assertMapper(mapper, expected); }
@Override public SqlStatementParameterCustomizer createForParameter(Annotation annotation, Class<?> sqlObjectType, Method method, Parameter param, int index, Type type) { return (stmt, arg) -> { final QualifiedType<?> mapTo; if (arg instanceof QualifiedType) { mapTo = (QualifiedType<?>) arg; } else if (arg instanceof GenericType) { mapTo = QualifiedType.of(((GenericType<?>) arg).getType()); } else if (arg instanceof Type) { mapTo = QualifiedType.of((Type) arg); } else { throw new UnsupportedOperationException("@MapTo must take a GenericType, QualifiedType, or Type, but got a " + arg.getClass().getName()); } ResultReturner returner = ResultReturner.forMethod(sqlObjectType, method); stmt.getConfig(SqlObjectStatementConfiguration.class).setReturner( () -> returner.mappedResult(((ResultBearing) stmt).mapTo(mapTo), stmt.getContext())); }; } }
private <C extends Collection<String>> void testCollectionType(GenericType<C> genericType) { Type containerType = genericType.getType(); Class<?> erasedType = getErasedType(containerType); assertThat(factory.accepts(containerType)).isTrue(); assertThat(factory.accepts(erasedType)).isFalse(); assertThat(factory.elementType(containerType)).contains(String.class); Collector<String, ?, C> collector = (Collector<String, ?, C>) factory.build(containerType); assertThat(Stream.of("foo", "bar", "baz").collect(collector)) .isInstanceOf(erasedType) .containsOnly("foo", "bar", "baz"); } }
private <C extends Collection<String>> void testCollectionType(GenericType<C> genericType) { Type containerType = genericType.getType(); Class<?> erasedType = getErasedType(containerType); assertThat(factory.accepts(containerType)).isTrue(); assertThat(factory.accepts(erasedType)).isFalse(); assertThat(factory.elementType(containerType)).contains(String.class); Collector<String, ?, C> collector = (Collector<String, ?, C>) factory.build(containerType); assertThat(Stream.of("foo", "bar", "baz").collect(collector)) .isInstanceOf(erasedType) .containsOnly("foo", "bar", "baz"); } }
@Test public void enumSet() { GenericType genericType = new GenericType<EnumSet<Color>>() {}; Type containerType = genericType.getType(); Class<?> erasedType = getErasedType(containerType); assertThat(factory.accepts(containerType)).isTrue(); assertThat(factory.accepts(erasedType)).isFalse(); assertThat(factory.elementType(containerType)).contains(Color.class); Collector<Color, ?, EnumSet<Color>> collector = (Collector<Color, ?, EnumSet<Color>>) factory.build(containerType); assertThat(Stream.of(Color.RED, Color.BLUE).collect(collector)) .isInstanceOf(erasedType) .containsExactly(Color.RED, Color.BLUE); }
@SuppressWarnings("unchecked") private <M extends Map<Long, String>> void testMapCollector(Class<? extends Map> erasedType, GenericType<M> genericType) { JdbiCollectors registry = dbRule.getJdbi().getConfig(JdbiCollectors.class); assertThat(registry.findElementTypeFor(genericType.getType())) .contains(new GenericType<Map.Entry<Long, String>>(){}.getType()); Collector<Map.Entry<Long, String>, ?, M> collector = (Collector<Map.Entry<Long, String>, ?, M>) registry .findFor(genericType.getType()) .orElseThrow(() -> new IllegalStateException("Missing collector for " + genericType)); M map = Stream.of(entry(1L, "foo"), entry(2L, "bar")).collect(collector); assertThat(map) .isInstanceOf(erasedType) .containsExactly(entry(1L, "foo"), entry(2L, "bar")); }
@SuppressWarnings("unchecked") private <M extends Multimap<Long, String>> void testMultimapCollector(Class<? extends Multimap> erasedType, GenericType<M> genericType) { JdbiCollectors registry = dbRule.getJdbi().getConfig(JdbiCollectors.class); assertThat(registry.findElementTypeFor(genericType.getType())) .contains(new GenericType<Map.Entry<Long, String>>(){}.getType()); Collector<Map.Entry<Long, String>, ?, M> collector = (Collector<Map.Entry<Long, String>, ?, M>) registry .findFor(genericType.getType()) .orElseThrow(() -> new IllegalStateException("Missing collector for " + genericType)); M map = Stream.of(entry(1L, "foo"), entry(2L, "bar")).collect(collector); assertThat(map) .isInstanceOf(erasedType) .containsAllEntriesOf(ImmutableMultimap.of(1L, "foo", 2L, "bar")); } }
private <M extends Map<Long, String>> void testMapType(GenericType<M> genericType) { Type containerType = genericType.getType(); Class<?> erasedType = getErasedType(containerType); assertThat(factory.accepts(containerType)).isTrue(); assertThat(factory.accepts(erasedType)).isFalse(); assertThat(factory.elementType(containerType)).contains(resolveMapEntryType(Long.class, String.class)); Collector<Map.Entry<Long, String>, ?, M> collector = (Collector<Map.Entry<Long, String>, ?, M>) factory.build(containerType); assertThat(Stream.of(entry(1L, "foo"), entry(2L, "bar"), entry(3L, "baz")).collect(collector)) .isInstanceOf(erasedType) .containsOnly(entry(1L, "foo"), entry(2L, "bar"), entry(3L, "baz")); assertThatThrownBy(() -> Stream.of(entry(1L, "foo"), entry(1L, "bar")).collect(collector)) .isInstanceOf(IllegalStateException.class) .hasMessageContaining("Multiple values"); } }