From adcb72fcfbca63e54e35b9134d997d3a0895e106 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Tue, 16 Apr 2019 15:34:24 +0200 Subject: [PATCH] [#7545] Add and to Add and as well as and to . The generator will warn about usage conflicting with the legacy , , and elements. --- .../java/org/jooq/meta/AbstractDatabase.java | 80 ++++--- .../java/org/jooq/meta/jaxb/ForcedType.java | 196 +++++++++++++++++- .../org/jooq/meta/jaxb/MatchersEnumType.java | 2 +- .../resources/xsd/jooq-codegen-3.12.0.xsd | 34 ++- .../main/java/org/jooq/tools/StringUtils.java | 16 ++ 5 files changed, 289 insertions(+), 39 deletions(-) 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 531527cfbc..91845a7070 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -1089,9 +1089,21 @@ public abstract class AbstractDatabase implements Database { ForcedType type = it2.next(); if (type.getExpressions() != null) { - type.setExpression(type.getExpressions()); + type.setIncludeExpression(type.getExpressions()); type.setExpressions(null); - log.warn("DEPRECATED", "The element in is deprecated. Use instead: " + type); + log.warn("DEPRECATED", "The element in is deprecated. Use instead: " + type); + } + + if (type.getExpression() != null) { + type.setIncludeExpression(type.getExpression()); + type.setExpression(null); + log.warn("DEPRECATED", "The element in is deprecated. Use instead: " + type); + } + + if (type.getTypes() != null) { + type.setIncludeTypes(type.getTypes()); + type.setTypes(null); + log.warn("DEPRECATED", "The element in is deprecated. Use instead: " + type); } if (StringUtils.isBlank(type.getName())) { @@ -1480,8 +1492,10 @@ public abstract class AbstractDatabase implements Database { // [#5885] Only the first matching is applied to the data type definition. forcedTypeLoop: for (ForcedType forcedType : getConfiguredForcedTypes()) { - String expression = StringUtils.defaultIfNull(forcedType.getExpressions(), forcedType.getExpression()); - String types = forcedType.getTypes(); + String excludeExpression = forcedType.getExcludeExpression(); + String includeExpression = StringUtils.firstNonNull(forcedType.getIncludeExpression(), forcedType.getExpression(), forcedType.getExpressions()); + String excludeTypes = forcedType.getExcludeTypes(); + String includeTypes = StringUtils.firstNonNull(forcedType.getIncludeTypes(), forcedType.getTypes()); Nullability nullability = forcedType.getNullability(); ForcedTypeObjectType objectType = forcedType.getObjectType(); String sql = forcedType.getSql(); @@ -1499,30 +1513,18 @@ public abstract class AbstractDatabase implements Database { || (nullability == Nullability.NULL && !definedType.isNullable()))) continue forcedTypeLoop; - if (expression != null) - if (!matches(patterns.pattern(expression), definition)) - continue forcedTypeLoop; + if ( (excludeExpression != null || includeExpression != null) + && filterExcludeInclude( + Collections.singletonList(definition), + new String[] { excludeExpression }, + new String[] { includeExpression != null ? includeExpression : ".*" }, + getFilters() + ).isEmpty()) + continue forcedTypeLoop; - if (types != null && definedType != null) { - Pattern p = patterns.pattern(types); - - if ( ( !p.matcher(definedType.getType()).matches() ) - && ( definedType.getLength() == 0 - || !p.matcher(definedType.getType() + "(" + definedType.getLength() + ")").matches()) - && ( definedType.getScale() != 0 - || !p.matcher(definedType.getType() + "(" + definedType.getPrecision() + ")").matches()) - && ( !p.matcher(definedType.getType() + "(" + definedType.getPrecision() + "," + definedType.getScale() + ")").matches() ) - && ( !p.matcher(definedType.getType() + "(" + definedType.getPrecision() + ", " + definedType.getScale() + ")").matches() ) - - // [#5872] We should match user-defined types as well, in case of which the type might be reported - // as USER-DEFINED (in PostgreSQL) - && ( StringUtils.isBlank(definedType.getUserType()) - || !p.matcher(definedType.getUserType()).matches() - && !p.matcher(definedType.getQualifiedUserType().unquotedName().toString()).matches() ) - ) { - continue forcedTypeLoop; - } - } + if ( (definedType != null && (excludeTypes != null || includeTypes != null)) + && !typeMatchesExcludeInclude(definedType, excludeTypes, includeTypes)) + continue forcedTypeLoop; if (sql != null) if (!matches(statements.fetchSet(sql), definition)) @@ -1534,6 +1536,30 @@ public abstract class AbstractDatabase implements Database { return null; } + private boolean typeMatchesExcludeInclude(DataTypeDefinition type, String exclude, String include) { + if (exclude != null && matches(type, patterns.pattern(exclude))) + return false; + + return include == null || matches(type, patterns.pattern(include)); + } + + private boolean matches(DataTypeDefinition type, Pattern pattern) { + return ( pattern.matcher(type.getType()).matches() ) + || ( type.getLength() != 0 + && pattern.matcher(type.getType() + "(" + type.getLength() + ")").matches() ) + || ( type.getScale() == 0 + && pattern.matcher(type.getType() + "(" + type.getPrecision() + ")").matches() ) + || ( pattern.matcher(type.getType() + "(" + type.getPrecision() + "," + type.getScale() + ")").matches() ) + || ( pattern.matcher(type.getType() + "(" + type.getPrecision() + ", " + type.getScale() + ")").matches() ) + + // [#5872] We should match user-defined types as well, in case of which the type might be reported + // as USER-DEFINED (in PostgreSQL) + || ( !StringUtils.isBlank(type.getUserType()) + && ( pattern.matcher(type.getUserType()).matches() + || pattern.matcher(type.getQualifiedUserType().unquotedName().toString()).matches() ) + ); + } + @Override public final void setConfiguredEmbeddables(List configuredEmbeddables) { this.configuredEmbeddables = configuredEmbeddables; 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 5b9506c591..c6a7c055f7 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 @@ -45,12 +45,20 @@ public class ForcedType implements Serializable @XmlJavaTypeAdapter(StringAdapter.class) protected String binding; @XmlJavaTypeAdapter(StringAdapter.class) + protected String excludeExpression; + @XmlJavaTypeAdapter(StringAdapter.class) + protected String includeExpression; + @XmlJavaTypeAdapter(StringAdapter.class) protected String expression; @XmlJavaTypeAdapter(StringAdapter.class) protected String expressions; @XmlJavaTypeAdapter(StringAdapter.class) protected String sql; @XmlJavaTypeAdapter(StringAdapter.class) + protected String excludeTypes; + @XmlJavaTypeAdapter(StringAdapter.class) + protected String includeTypes; + @XmlJavaTypeAdapter(StringAdapter.class) protected String types; @XmlElement(defaultValue = "ALL") @XmlSchemaType(name = "string") @@ -184,8 +192,58 @@ public class ForcedType implements Serializable /** * A Java regular expression matching columns, parameters, attributes, - * etc to be forced to have this type. If provided, both "expressions" and - * "types" must match. + * etc. which must not have this type. Excludes match before includes, i.e. + * excludes have a higher priority. + * + * @return + * possible object is + * {@link String } + * + */ + public String getExcludeExpression() { + return excludeExpression; + } + + /** + * Sets the value of the excludeExpression property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setExcludeExpression(String value) { + this.excludeExpression = value; + } + + /** + * A Java regular expression matching columns, parameters, attributes, + * etc. to be forced to have this type. If provided, both "includeExpression" and + * "includeTypes" must match. + * + * @return + * possible object is + * {@link String } + * + */ + public String getIncludeExpression() { + return includeExpression; + } + + /** + * Sets the value of the includeExpression property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setIncludeExpression(String value) { + this.includeExpression = value; + } + + /** + * The same as {@link #getIncludeExpression()}. This is kept for backwards compatibility reasons. * * @return * possible object is @@ -209,7 +267,7 @@ public class ForcedType implements Serializable } /** - * The same as expression. This is kept for backwards compatibility reasons. + * The same as {@link #getIncludeExpression()}. This is kept for backwards compatibility reasons. * * @return * possible object is @@ -256,9 +314,59 @@ public class ForcedType implements Serializable this.sql = value; } + /** + * A Java regular expression matching data types + * which must not have this type. Excludes match before includes, i.e. + * excludes have a higher priority. + * + * @return + * possible object is + * {@link String } + * + */ + public String getExcludeTypes() { + return excludeTypes; + } + + /** + * Sets the value of the excludeTypes property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setExcludeTypes(String value) { + this.excludeTypes = value; + } + /** * A Java regular expression matching data types to be forced to have this - * type. If provided, both "expression" and "types" must match. + * type. If provided, both "includeExpression" and "includeTypes" must match. + * + * @return + * possible object is + * {@link String } + * + */ + public String getIncludeTypes() { + return includeTypes; + } + + /** + * Sets the value of the includeTypes property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setIncludeTypes(String value) { + this.includeTypes = value; + } + + /** + * The same as {@link #getIncludeTypes()}. This is kept for backwards compatibility reasons. * * @return * possible object is @@ -354,6 +462,16 @@ public class ForcedType implements Serializable return this; } + public ForcedType withExcludeExpression(String value) { + setExcludeExpression(value); + return this; + } + + public ForcedType withIncludeExpression(String value) { + setIncludeExpression(value); + return this; + } + public ForcedType withExpression(String value) { setExpression(value); return this; @@ -369,6 +487,16 @@ public class ForcedType implements Serializable return this; } + public ForcedType withExcludeTypes(String value) { + setExcludeTypes(value); + return this; + } + + public ForcedType withIncludeTypes(String value) { + setIncludeTypes(value); + return this; + } + public ForcedType withTypes(String value) { setTypes(value); return this; @@ -412,6 +540,16 @@ public class ForcedType implements Serializable sb.append(binding); sb.append(""); } + if ((excludeExpression!= null)&&(!"".equals(excludeExpression))) { + sb.append(""); + sb.append(excludeExpression); + sb.append(""); + } + if ((includeExpression!= null)&&(!"".equals(includeExpression))) { + sb.append(""); + sb.append(includeExpression); + sb.append(""); + } if ((expression!= null)&&(!"".equals(expression))) { sb.append(""); sb.append(expression); @@ -427,6 +565,16 @@ public class ForcedType implements Serializable sb.append(sql); sb.append(""); } + if ((excludeTypes!= null)&&(!"".equals(excludeTypes))) { + sb.append(""); + sb.append(excludeTypes); + sb.append(""); + } + if ((includeTypes!= null)&&(!"".equals(includeTypes))) { + sb.append(""); + sb.append(includeTypes); + sb.append(""); + } if ((types!= null)&&(!"".equals(types))) { sb.append(""); sb.append(types); @@ -502,6 +650,24 @@ public class ForcedType implements Serializable return false; } } + if (excludeExpression == null) { + if (other.excludeExpression!= null) { + return false; + } + } else { + if (!excludeExpression.equals(other.excludeExpression)) { + return false; + } + } + if (includeExpression == null) { + if (other.includeExpression!= null) { + return false; + } + } else { + if (!includeExpression.equals(other.includeExpression)) { + return false; + } + } if (expression == null) { if (other.expression!= null) { return false; @@ -529,6 +695,24 @@ public class ForcedType implements Serializable return false; } } + if (excludeTypes == null) { + if (other.excludeTypes!= null) { + return false; + } + } else { + if (!excludeTypes.equals(other.excludeTypes)) { + return false; + } + } + if (includeTypes == null) { + if (other.includeTypes!= null) { + return false; + } + } else { + if (!includeTypes.equals(other.includeTypes)) { + return false; + } + } if (types == null) { if (other.types!= null) { return false; @@ -568,9 +752,13 @@ public class ForcedType implements Serializable result = ((prime*result)+((converter == null)? 0 :converter.hashCode())); result = ((prime*result)+((enumConverter == null)? 0 :enumConverter.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())); result = ((prime*result)+((expression == null)? 0 :expression.hashCode())); result = ((prime*result)+((expressions == null)? 0 :expressions.hashCode())); result = ((prime*result)+((sql == null)? 0 :sql.hashCode())); + result = ((prime*result)+((excludeTypes == null)? 0 :excludeTypes.hashCode())); + result = ((prime*result)+((includeTypes == null)? 0 :includeTypes.hashCode())); result = ((prime*result)+((types == null)? 0 :types.hashCode())); result = ((prime*result)+((nullability == null)? 0 :nullability.hashCode())); result = ((prime*result)+((objectType == null)? 0 :objectType.hashCode())); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/MatchersEnumType.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/MatchersEnumType.java index 6bbb0b456f..0be4ab9615 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/MatchersEnumType.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/MatchersEnumType.java @@ -40,7 +40,7 @@ public class MatchersEnumType implements Serializable protected String enumImplements; /** - * This sequence matcher applies to all unqualified or qualified enum names matched by this expression. If left empty, this matcher applies to all enums. + * This enum matcher applies to all unqualified or qualified enum names matched by this expression. If left empty, this matcher applies to all enums. * * @return * possible object is diff --git a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.12.0.xsd b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.12.0.xsd index 5ee75fa2fd..2ee4024ad7 100644 --- a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.12.0.xsd +++ b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.12.0.xsd @@ -344,7 +344,7 @@ - + @@ -935,23 +935,43 @@ or {@link #getBinding()} is required]]> - + +etc. which must not have this type. Excludes match before includes, i.e. +excludes have a higher priority.]]> + + + + + + + + - + - + + + + + +type. If provided, both "includeExpression" and "includeTypes" must match.]]> + + + + diff --git a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java index a2ebb8bd19..0f04a232a7 100644 --- a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java +++ b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java @@ -1302,6 +1302,22 @@ public final class StringUtils { return object != null ? object : defaultValue; } + /** + *

Returns the first non-{@code null} argument.

+ * + * @param the type of the objects + * @param objects the elements to test, may not be {@code null} but empty + * @return first non-{@code null} element in {@code objects}, otherwise {@code null} + */ + @SafeVarargs + public static T firstNonNull(T... objects) { + for (T object : objects) { + if (object != null) + return object; + } + return null; + } + // ------------------------------------------------------------------------- // XXX: The following methods are not part of Apache's commons-lang library // -------------------------------------------------------------------------