diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index 6c9b41f5de..e0fd7e2178 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -1310,8 +1310,9 @@ public abstract class AbstractDatabase implements Database { if (StringUtils.isBlank(type.getBinding()) && StringUtils.isBlank(type.getConverter()) && - !Boolean.TRUE.equals(type.isEnumConverter())) { - log.warn("Bad configuration for . Either or or is required: " + type); + !Boolean.TRUE.equals(type.isEnumConverter()) && + type.getLambdaConverter() == null) { + log.warn("Bad configuration for . Either or or or is required: " + type); it2.remove(); continue; @@ -1334,6 +1335,10 @@ public abstract class AbstractDatabase implements Database { log.warn("Bad configuration for . is not allowed when is provided: " + type); type.setEnumConverter(null); } + if (type.getLambdaConverter() != null) { + log.warn("Bad configuration for . is not allowed when is provided: " + type); + type.setLambdaConverter(null); + } } if (type.getUserType() != null && StringUtils.equals(type.getUserType(), typeName)) { diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java index d530361dbd..ac9f09dbe1 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java @@ -38,6 +38,7 @@ package org.jooq.meta; +import static java.lang.Boolean.FALSE; import static org.jooq.tools.Convert.convert; import static org.jooq.tools.StringUtils.isEmpty; @@ -57,6 +58,7 @@ import org.jooq.impl.EnumConverter; import org.jooq.impl.SQLDataType; import org.jooq.meta.jaxb.CustomType; import org.jooq.meta.jaxb.ForcedType; +import org.jooq.meta.jaxb.LambdaConverter; import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; @@ -225,21 +227,14 @@ public abstract class AbstractTypedElementDefinition // [#5877] [#6567] EnumConverters profit from simplified configuration if (Boolean.TRUE.equals(customType.isEnumConverter()) || EnumConverter.class.getName().equals(customType.getConverter())) { - - String tType = Object.class.getName(); - - if (resolver != null) - tType = resolver.resolve(definedType); - else - try { - tType = getDataType(db, definedType.getType(), definedType.getPrecision(), definedType.getScale()) - .getType() - .getName(); - } - catch (SQLDialectNotSupportedException ignore) {} - + String tType = tType(db, resolver, definedType); converter = "new " + EnumConverter.class.getName() + "<" + tType + ", " + uType + ">(" + tType + ".class, " + uType + ".class)"; } + else if (customType.getLambdaConverter() != null) { + LambdaConverter c = customType.getLambdaConverter(); + String tType = tType(db, resolver, definedType); + converter = "org.jooq.Converter.of" + (!FALSE.equals(c.isNullable()) ? "Nullable" : "") + "(" + tType + ".class, " + uType + ".class, " + c.getFrom() + ", " + c.getTo() + ")"; + } else if (!StringUtils.isBlank(customType.getConverter())) { converter = customType.getConverter(); } @@ -309,6 +304,20 @@ public abstract class AbstractTypedElementDefinition return result; } + private static final String tType(Database db, JavaTypeResolver resolver, DataTypeDefinition definedType) { + if (resolver != null) + return resolver.resolve(definedType); + + try { + return getDataType(db, definedType.getType(), definedType.getPrecision(), definedType.getScale()) + .getType() + .getName(); + } + catch (SQLDialectNotSupportedException ignore) { + return Object.class.getName(); + } + } + @SuppressWarnings("deprecation") public static final CustomType customType(Database db, ForcedType forcedType) { String name = forcedType.getName(); @@ -328,6 +337,7 @@ public abstract class AbstractTypedElementDefinition return new CustomType() .withBinding(forcedType.getBinding()) .withEnumConverter(forcedType.isEnumConverter()) + .withLambdaConverter(forcedType.getLambdaConverter()) .withConverter(forcedType.getConverter()) .withName(name) .withType(forcedType.getUserType()); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/CustomType.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/CustomType.java index dcb79cbcb1..621d8290e0 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/CustomType.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/CustomType.java @@ -38,6 +38,7 @@ public class CustomType implements Serializable, XMLAppendable @XmlJavaTypeAdapter(StringAdapter.class) protected String converter; protected Boolean enumConverter; + protected LambdaConverter lambdaConverter; @XmlJavaTypeAdapter(StringAdapter.class) protected String binding; @@ -121,6 +122,24 @@ public class CustomType implements Serializable, XMLAppendable this.enumConverter = value; } + /** + * @deprecated Use ForcedType only + * + */ + @Deprecated + public LambdaConverter getLambdaConverter() { + return lambdaConverter; + } + + /** + * @deprecated Use ForcedType only + * + */ + @Deprecated + public void setLambdaConverter(LambdaConverter value) { + this.lambdaConverter = value; + } + /** * @deprecated Use ForcedType only * @@ -174,6 +193,16 @@ public class CustomType implements Serializable, XMLAppendable return this; } + /** + * @deprecated Use ForcedType only + * + */ + @Deprecated + public CustomType withLambdaConverter(LambdaConverter value) { + setLambdaConverter(value); + return this; + } + /** * @deprecated Use ForcedType only * @@ -190,6 +219,7 @@ public class CustomType implements Serializable, XMLAppendable builder.append("type", type); builder.append("converter", converter); builder.append("enumConverter", enumConverter); + builder.append("lambdaConverter", lambdaConverter); builder.append("binding", binding); } @@ -248,6 +278,15 @@ public class CustomType implements Serializable, XMLAppendable return false; } } + if (lambdaConverter == null) { + if (other.lambdaConverter!= null) { + return false; + } + } else { + if (!lambdaConverter.equals(other.lambdaConverter)) { + return false; + } + } if (binding == null) { if (other.binding!= null) { return false; @@ -268,6 +307,7 @@ public class CustomType implements Serializable, XMLAppendable result = ((prime*result)+((type == null)? 0 :type.hashCode())); result = ((prime*result)+((converter == null)? 0 :converter.hashCode())); result = ((prime*result)+((enumConverter == null)? 0 :enumConverter.hashCode())); + result = ((prime*result)+((lambdaConverter == null)? 0 :lambdaConverter.hashCode())); result = ((prime*result)+((binding == null)? 0 :binding.hashCode())); return result; } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ForcedType.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ForcedType.java index d784ddf04e..a7079524e9 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ForcedType.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ForcedType.java @@ -37,6 +37,7 @@ public class ForcedType implements Serializable, XMLAppendable @XmlJavaTypeAdapter(StringAdapter.class) protected String converter; protected Boolean enumConverter; + protected LambdaConverter lambdaConverter; @XmlJavaTypeAdapter(StringAdapter.class) protected String binding; @XmlJavaTypeAdapter(StringAdapter.class) @@ -140,6 +141,22 @@ public class ForcedType implements Serializable, XMLAppendable this.enumConverter = value; } + /** + * A lambda converter implementation for the {@link #getUserType()}. + * + */ + public LambdaConverter getLambdaConverter() { + return lambdaConverter; + } + + /** + * A lambda converter implementation for the {@link #getUserType()}. + * + */ + public void setLambdaConverter(LambdaConverter value) { + this.lambdaConverter = value; + } + /** * A {@link org.jooq.Binding} implementation for the custom type. * @@ -365,6 +382,15 @@ public class ForcedType implements Serializable, XMLAppendable return this; } + /** + * A lambda converter implementation for the {@link #getUserType()}. + * + */ + public ForcedType withLambdaConverter(LambdaConverter value) { + setLambdaConverter(value); + return this; + } + /** * A {@link org.jooq.Binding} implementation for the custom type. * @@ -477,6 +503,7 @@ public class ForcedType implements Serializable, XMLAppendable builder.append("userType", userType); builder.append("converter", converter); builder.append("enumConverter", enumConverter); + builder.append("lambdaConverter", lambdaConverter); builder.append("binding", binding); builder.append("excludeExpression", excludeExpression); builder.append("includeExpression", includeExpression); @@ -545,6 +572,15 @@ public class ForcedType implements Serializable, XMLAppendable return false; } } + if (lambdaConverter == null) { + if (other.lambdaConverter!= null) { + return false; + } + } else { + if (!lambdaConverter.equals(other.lambdaConverter)) { + return false; + } + } if (binding == null) { if (other.binding!= null) { return false; @@ -655,6 +691,7 @@ public class ForcedType implements Serializable, XMLAppendable result = ((prime*result)+((userType == null)? 0 :userType.hashCode())); result = ((prime*result)+((converter == null)? 0 :converter.hashCode())); result = ((prime*result)+((enumConverter == null)? 0 :enumConverter.hashCode())); + result = ((prime*result)+((lambdaConverter == null)? 0 :lambdaConverter.hashCode())); result = ((prime*result)+((binding == null)? 0 :binding.hashCode())); result = ((prime*result)+((excludeExpression == null)? 0 :excludeExpression.hashCode())); result = ((prime*result)+((includeExpression == null)? 0 :includeExpression.hashCode())); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/LambdaConverter.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/LambdaConverter.java new file mode 100644 index 0000000000..1e6593e5ff --- /dev/null +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/LambdaConverter.java @@ -0,0 +1,186 @@ + +package org.jooq.meta.jaxb; + +import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.jooq.util.jaxb.tools.StringAdapter; +import org.jooq.util.jaxb.tools.XMLAppendable; +import org.jooq.util.jaxb.tools.XMLBuilder; + + +/** + * A converter taking two lambda definitions. + * + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "LambdaConverter", propOrder = { + +}) +@SuppressWarnings({ + "all" +}) +public class LambdaConverter implements Serializable, XMLAppendable +{ + + private final static long serialVersionUID = 31400L; + @XmlElement(required = true) + @XmlJavaTypeAdapter(StringAdapter.class) + protected String from; + @XmlElement(required = true) + @XmlJavaTypeAdapter(StringAdapter.class) + protected String to; + @XmlElement(defaultValue = "true") + protected Boolean nullable = true; + + /** + * The implementation of {@link org.jooq.Converter#from(Object)}. + * + */ + public String getFrom() { + return from; + } + + /** + * The implementation of {@link org.jooq.Converter#from(Object)}. + * + */ + public void setFrom(String value) { + this.from = value; + } + + /** + * The implementation of {@link org.jooq.Converter#to(Object)}. + * + */ + public String getTo() { + return to; + } + + /** + * The implementation of {@link org.jooq.Converter#to(Object)}. + * + */ + public void setTo(String value) { + this.to = value; + } + + /** + * Whether to use {@link org.jooq.Converter#ofNullable(Class, Class, java.util.function.Function, java.util.function.Function)} or {@link org.jooq.Converter#of(Class, Class, java.util.function.Function, java.util.function.Function)}. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isNullable() { + return nullable; + } + + /** + * Sets the value of the nullable property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setNullable(Boolean value) { + this.nullable = value; + } + + /** + * The implementation of {@link org.jooq.Converter#from(Object)}. + * + */ + public LambdaConverter withFrom(String value) { + setFrom(value); + return this; + } + + /** + * The implementation of {@link org.jooq.Converter#to(Object)}. + * + */ + public LambdaConverter withTo(String value) { + setTo(value); + return this; + } + + public LambdaConverter withNullable(Boolean value) { + setNullable(value); + return this; + } + + @Override + public final void appendTo(XMLBuilder builder) { + builder.append("from", from); + builder.append("to", to); + builder.append("nullable", nullable); + } + + @Override + public String toString() { + XMLBuilder builder = XMLBuilder.nonFormatting(); + appendTo(builder); + return builder.toString(); + } + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass()!= that.getClass()) { + return false; + } + LambdaConverter other = ((LambdaConverter) that); + if (from == null) { + if (other.from!= null) { + return false; + } + } else { + if (!from.equals(other.from)) { + return false; + } + } + if (to == null) { + if (other.to!= null) { + return false; + } + } else { + if (!to.equals(other.to)) { + return false; + } + } + if (nullable == null) { + if (other.nullable!= null) { + return false; + } + } else { + if (!nullable.equals(other.nullable)) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = ((prime*result)+((from == null)? 0 :from.hashCode())); + result = ((prime*result)+((to == null)? 0 :to.hashCode())); + result = ((prime*result)+((nullable == null)? 0 :nullable.hashCode())); + return result; + } + +} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java index 1e58a7f280..db1fb55d75 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java @@ -213,6 +213,14 @@ public class ObjectFactory { return new ForcedType(); } + /** + * Create an instance of {@link LambdaConverter } + * + */ + public LambdaConverter createLambdaConverter() { + return new LambdaConverter(); + } + /** * Create an instance of {@link Generate } * diff --git a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.14.0.xsd b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.14.0.xsd index 88ba454ce5..6296ee215c 100644 --- a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.14.0.xsd +++ b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.14.0.xsd @@ -1042,6 +1042,18 @@ for Oracle.]]> + + + + + + + + @java.lang.Deprecated + @java.lang.Deprecated + + + @@ -1145,6 +1157,10 @@ or {@link #getBinding()} is required]]> + + + + @@ -1199,6 +1215,23 @@ type. If provided, both "includeExpression" and "includeTypes" must match.]]> + + + + + + + + + + + + + + + + +