[#650] Add a data type registry "org.jooq.impl.DataTypes" for cleaner DataType referencing

[#1217] Add EnumConverter as a base type for custom enum converters
This commit is contained in:
Lukas Eder 2012-03-04 15:55:00 +00:00
parent 880786ff07
commit a47284df8d
7 changed files with 277 additions and 5 deletions

View File

@ -40,6 +40,11 @@ import org.jooq.Converter;
public class MyEnumNumericMapper implements Converter<Integer, MyEnum> {
/**
* Generated UID
*/
private static final long serialVersionUID = -4252074829213730476L;
public static final MyEnumNumericMapper INSTANCE = new MyEnumNumericMapper();
@Override

View File

@ -39,7 +39,12 @@ import org.jooq.Converter;
public class MyEnumStringMapper implements Converter<String, MyEnum> {
public static final MyEnumStringMapper INSTANCE = new MyEnumStringMapper();
/**
* Generated UID
*/
private static final long serialVersionUID = -4252074829213730476L;
public static final MyEnumStringMapper INSTANCE = new MyEnumStringMapper();
@Override
public MyEnum from(String t) {

View File

@ -274,6 +274,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
assertEquals(dateOfBirth, record.getValueAsTime(TAuthor_DATE_OF_BIRTH()).getTime());
}
@SuppressWarnings("serial")
@Test
public void testCustomConversion() {
Converter<String, StringBuilder> converter = new Converter<String, StringBuilder>() {

View File

@ -35,6 +35,8 @@
*/
package org.jooq;
import java.io.Serializable;
import org.jooq.impl.SQLDataType;
/**
@ -49,17 +51,17 @@ import org.jooq.impl.SQLDataType;
* <li>to store user types converting them to database types "TO" the database.
* Hence, {@link #toType()} is the user-defined type</li>
* </ul>
*
*
* @author Lukas Eder
* @param <T> The database type - i.e. any type available from
* {@link SQLDataType}
* @param <U> The user type
*/
public interface Converter<T, U> {
public interface Converter<T, U> extends Serializable {
/**
* Convert a database object to a user object
*
*
* @param databaseObject The database object
* @return The user object
*/
@ -67,7 +69,7 @@ public interface Converter<T, U> {
/**
* Convert a user object to a database object
*
*
* @param userObject The user object
* @return The database object
*/

View File

@ -0,0 +1,132 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq.impl;
import java.util.HashMap;
import java.util.Map;
import org.jooq.Converter;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.exception.DataTypeException;
/**
* A central {@link DataType} registry
*
* @author Lukas Eder
*/
public final class DataTypes {
private static final Object INIT_LOCK = new Object();
private static final Map<Class<?>, Converter<?, ?>> CONVERTERS = new HashMap<Class<?>, Converter<?, ?>>();
// ------------------------------------------------------------------------
// XXX: Public API used for initialisation from generated artefacts
// ------------------------------------------------------------------------
/**
* Register a <code>Converter</code> for a custom type
* <p>
* This registers a {@link Converter} for a custom type. This converter will
* be used by jOOQ to recognise custom types and to transform them back to
* well-known database types (as defined in {@link Converter#fromType()}) in
* rendering and binding steps
* <p>
* A custom type can be registered only once. Duplicate registrations will
* be ignored
* <p>
* The converter class must provide a default constructor.
*
* @see #registerConverter(Class, Converter)
*/
public static final synchronized <U> void registerConverter(Class<U> customType,
Class<? extends Converter<?, U>> converter) {
try {
converter.getConstructor().setAccessible(true);
registerConverter(customType, converter.newInstance());
}
catch (Exception e) {
throw new DataTypeException("Cannot register converter", e);
}
}
/**
* Register a <code>Converter</code> for a custom type
* <p>
* This registers a {@link Converter} for a custom type. This converter will
* be used by jOOQ to recognise custom types and to transform them back to
* well-known database types (as defined in {@link Converter#fromType()}) in
* rendering and binding steps
* <p>
* A custom type can be registered only once. Duplicate registrations will
* be ignored
*/
public static final synchronized <U> void registerConverter(Class<U> customType, Converter<?, U> converter) {
// A converter can be registered only once
if (!CONVERTERS.containsKey(customType)) {
CONVERTERS.put(customType, converter);
}
}
/**
* Register a <code>Converter</code> for a field
* <p>
* This registers a converter for a specific field in your generated schema.
* This converter will be used by jOOQ to convert database types to your own
* custom types and deliver those types in {@link Record} and {@link Result}
*/
public static final synchronized <T> void registerConverter(Field<T> field, Converter<T, ?> converter) {
}
// ------------------------------------------------------------------------
// XXX: Internal API
// ------------------------------------------------------------------------
@SuppressWarnings("unchecked")
static final <U> Converter<?, U> converter(Class<U> customType) {
return (Converter<?, U>) CONVERTERS.get(customType);
}
/**
* No instances
*/
private DataTypes() {}
}

View File

@ -0,0 +1,121 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq.impl;
import static org.jooq.tools.Convert.convert;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jooq.Converter;
/**
* A base class for enum conversion.
*
* @author Lukas Eder
*/
public class EnumConverter<T, U extends Enum<U>> implements Converter<T, U> {
/**
* Generated UID
*/
private static final long serialVersionUID = -6094337837408829491L;
private final Class<T> fromType;
private final Class<U> toType;
private final Map<T, U> lookup;
private final EnumType enumType;
public EnumConverter(Class<T> fromType, Class<U> toType) {
this.fromType = fromType;
this.toType = toType;
this.enumType = Number.class.isAssignableFrom(fromType) ? EnumType.ORDINAL : EnumType.STRING;
this.lookup = new LinkedHashMap<T, U>();
for (U u : toType.getEnumConstants()) {
this.lookup.put(to(u), u);
}
}
@Override
public final U from(T databaseObject) {
return lookup.get(databaseObject);
}
/**
* Subclasses may override this method to provide a custom reverse mapping
* implementation
* <p>
* {@inheritDoc}
*/
@Override
public T to(U userObject) {
if (enumType == EnumType.ORDINAL) {
return convert(userObject.ordinal(), fromType);
}
else {
return convert(userObject.name(), fromType);
}
}
@Override
public final Class<T> fromType() {
return fromType;
}
@Override
public final Class<U> toType() {
return toType;
}
/**
* The type of the converted <code>Enum</code>.
* <p>
* This corresponds to JPA's <code>EnumType</code>
*/
enum EnumType {
/**
* Ordinal enum type
*/
ORDINAL,
/**
* String enum type
*/
STRING
}
}

View File

@ -310,6 +310,11 @@ public final class Convert {
*/
private static class ConvertAll<U> implements Converter<Object, U> {
/**
* Generated UID
*/
private static final long serialVersionUID = 2508560107067092501L;
private final Class<? extends U> toClass;
ConvertAll(Class<? extends U> toClass) {
@ -465,6 +470,7 @@ public final class Convert {
return Object.class;
}
@SuppressWarnings("unchecked")
@Override
public Class<U> toType() {
return (Class<U>) toClass;