From 100b2dee35d06d068746e99e22ea7484179da134 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Tue, 30 May 2017 12:16:57 +0200 Subject: [PATCH] [#4846] Add SPI to allow for injecting meta data ordering --- .../java/org/jooq/util/GenerationTool.java | 10 +++ .../resources/org/jooq/web/manual-3.10.xml | 88 +++++++++++++++++++ .../src/main/java/META-INF/sun-jaxb.episode | 6 ++ .../java/org/jooq/util/AbstractDatabase.java | 36 ++++++-- .../AbstractElementContainerDefinition.java | 2 + .../src/main/java/org/jooq/util/Database.java | 16 ++++ .../java/org/jooq/util/jaxb/Database.java | 34 +++++++ .../resources/xsd/jooq-codegen-3.10.0.xsd | 6 ++ 8 files changed, 190 insertions(+), 8 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/util/GenerationTool.java b/jOOQ-codegen/src/main/java/org/jooq/util/GenerationTool.java index 751921ec8b..2ee63e7d79 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/util/GenerationTool.java +++ b/jOOQ-codegen/src/main/java/org/jooq/util/GenerationTool.java @@ -52,6 +52,7 @@ import java.io.StringWriter; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; +import java.util.Comparator; import java.util.List; import java.util.Properties; @@ -478,6 +479,15 @@ public class GenerationTool { database.setSchemaVersionProvider(svp); database.setCatalogVersionProvider(cvp); + if (!StringUtils.isBlank(d.getOrderProvider())) { + Class orderProvider = Class.forName(d.getOrderProvider()); + + if (Comparator.class.isAssignableFrom(orderProvider)) + database.setOrderProvider((Comparator) orderProvider.newInstance()); + else + log.warn("Order provider must be of type java.util.Comparator: " + orderProvider); + } + if (d.getEnumTypes().size() > 0) log.warn("DEPRECATED", "The configuration property /configuration/generator/database/enumTypes is experimental and deprecated and will be removed in the future."); if (Boolean.TRUE.equals(d.isDateAsTimestamp())) diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.10.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.10.xml index 3fa0d0e656..bf6cd65da5 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.10.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.10.xml @@ -15710,6 +15710,94 @@ configuration { +
+ Custom ordering of generated code + +

+ By default, the jOOQ code generator maintains the following ordering of objects: +

+ +
    +
  • Catalogs, schemas, tables, user-defined types, packages, routines, sequences, constraints are ordered alphabetically
  • +
  • Table columns, user-defined type attributes, routine parameters are ordered in their order of definition
  • +
+ +

+ Sometimes, it may be desireable to override this default ordering to a custom ordering. In particular, the default ordering may be case-sensitive, when case-insensitive ordering is really more desireable at times. Users may define an order provider by specifying a fully qualified class on the code generator's class path, which must implement as follows: +

+ +

+ XML configuration (standalone and Maven) +

+ + + + + com.example.CaseInsensitiveOrderProvider + + +]]> + +

+ Programmatic configuration +

+ + + +

+ Gradle configuration +

+ + + +

+ This order provider may then look as follows: +

+ + { + @Override + public int compare(Definition o1, Definition o2) { + return o1.getQualifiedInputName().compareToIgnoreCase(o2.getQualifiedInputName()); + } +}]]> +

+ While changing the order of "top level types" (like tables) is irrelevant to the jOOQ runtime, there may be some side-effects to changing the order of table columns, user-defined type attributes, routine parameters, as the database might expect the exact same order as is defined in the database. In order to only change the ordering for tables, the following order provider can be implemented instead: +

+ + { + @Override + public int compare(Definition o1, Definition o2) { + if (o1 instanceof TableDefinition && o2 instanceof TableDefinition) + return o1.getQualifiedInputName().compareToIgnoreCase(o2.getQualifiedInputName()); + else + return 0; // Retain input ordering + } +}]]> +
+
+
Forced types diff --git a/jOOQ-meta/src/main/java/META-INF/sun-jaxb.episode b/jOOQ-meta/src/main/java/META-INF/sun-jaxb.episode index 6de6320468..9b6ad9cac1 100644 --- a/jOOQ-meta/src/main/java/META-INF/sun-jaxb.episode +++ b/jOOQ-meta/src/main/java/META-INF/sun-jaxb.episode @@ -77,12 +77,18 @@ + + + + + + diff --git a/jOOQ-meta/src/main/java/org/jooq/util/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/util/AbstractDatabase.java index 6dcfbd3ebd..96bc1d0199 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/AbstractDatabase.java @@ -46,6 +46,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -128,6 +129,7 @@ public abstract class AbstractDatabase implements Database { private List configuredForcedTypes; private SchemaVersionProvider schemaVersionProvider; private CatalogVersionProvider catalogVersionProvider; + private Comparator orderProvider; // ------------------------------------------------------------------------- // Loaded definitions @@ -998,6 +1000,16 @@ public abstract class AbstractDatabase implements Database { this.catalogVersionProvider = catalogVersionProvider; } + @Override + public final Comparator getOrderProvider() { + return orderProvider; + } + + @Override + public final void setOrderProvider(Comparator provider) { + this.orderProvider = provider; + } + @Override public final void setSupportsUnsignedTypes(boolean supportsUnsignedTypes) { this.supportsUnsignedTypes = supportsUnsignedTypes; @@ -1057,7 +1069,7 @@ public abstract class AbstractDatabase implements Database { try { List s = getSequences0(); - sequences = filterExcludeInclude(s); + sequences = sort(filterExcludeInclude(s)); log.info("Sequences fetched", fetchedSize(s, sequences)); } catch (Exception e) { @@ -1159,7 +1171,7 @@ public abstract class AbstractDatabase implements Database { try { List t = getTables0(); - tables = filterExcludeInclude(t); + tables = sort(filterExcludeInclude(t)); log.info("Tables fetched", fetchedSize(t, tables)); } catch (Exception e) { @@ -1204,7 +1216,7 @@ public abstract class AbstractDatabase implements Database { try { List e = getEnums0(); - enums = filterExcludeInclude(e); + enums = sort(filterExcludeInclude(e)); enums.addAll(getConfiguredEnums()); log.info("Enums fetched", fetchedSize(e, enums)); @@ -1310,7 +1322,7 @@ public abstract class AbstractDatabase implements Database { try { List e = getDomains0(); - domains = filterExcludeInclude(e); + domains = sort(filterExcludeInclude(e)); log.info("Domains fetched", fetchedSize(e, domains)); } catch (Exception e) { @@ -1350,7 +1362,7 @@ public abstract class AbstractDatabase implements Database { try { List a = getArrays0(); - arrays = filterExcludeInclude(a); + arrays = sort(filterExcludeInclude(a)); log.info("ARRAYs fetched", fetchedSize(a, arrays)); } catch (Exception e) { @@ -1395,7 +1407,7 @@ public abstract class AbstractDatabase implements Database { try { List u = getUDTs0(); - udts = filterExcludeInclude(u); + udts = sort(filterExcludeInclude(u)); log.info("UDTs fetched", fetchedSize(u, udts)); } catch (Exception e) { @@ -1481,7 +1493,7 @@ public abstract class AbstractDatabase implements Database { try { List r = getRoutines0(); - routines = filterExcludeInclude(r); + routines = sort(filterExcludeInclude(r)); log.info("Routines fetched", fetchedSize(r, routines)); } catch (Exception e) { @@ -1507,7 +1519,7 @@ public abstract class AbstractDatabase implements Database { try { List p = getPackages0(); - packages = filterExcludeInclude(p); + packages = sort(filterExcludeInclude(p)); log.info("Packages fetched", fetchedSize(p, packages)); } catch (Exception e) { @@ -1595,6 +1607,14 @@ public abstract class AbstractDatabase implements Database { return result; } + @Override + public final List sort(List definitions) { + if (orderProvider != null) + Collections.sort(definitions, orderProvider); + + return definitions; + } + @Override public final List getIncluded() { return Collections.unmodifiableList(included); diff --git a/jOOQ-meta/src/main/java/org/jooq/util/AbstractElementContainerDefinition.java b/jOOQ-meta/src/main/java/org/jooq/util/AbstractElementContainerDefinition.java index 4b3796c16a..3f2178a024 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/AbstractElementContainerDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/AbstractElementContainerDefinition.java @@ -127,6 +127,8 @@ extends AbstractDefinition { else { elements = e; } + + db.sort(elements); } catch (Exception e) { log.error("Error while initialising type", e); diff --git a/jOOQ-meta/src/main/java/org/jooq/util/Database.java b/jOOQ-meta/src/main/java/org/jooq/util/Database.java index 953d39a7a8..1279d60a71 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/Database.java @@ -36,6 +36,7 @@ package org.jooq.util; import java.sql.Connection; +import java.util.Comparator; import java.util.List; import java.util.Properties; @@ -463,6 +464,11 @@ public interface Database { */ List filterExcludeInclude(List definitions); + /** + * Sort a list of definitions according to the {@link #getOrderProvider()} defined in this database. + */ + List sort(List definitions); + /** * Retrieve all included objects. */ @@ -612,6 +618,16 @@ public interface Database { */ void setCatalogVersionProvider(CatalogVersionProvider provider); + /** + * The database's order provider. + */ + Comparator getOrderProvider(); + + /** + * The database's order provider. + */ + void setOrderProvider(Comparator provider); + /** * Database objects matching any of these field names will be generated as * forced types. diff --git a/jOOQ-meta/src/main/java/org/jooq/util/jaxb/Database.java b/jOOQ-meta/src/main/java/org/jooq/util/jaxb/Database.java index 418e1b0cf4..0813f438e7 100644 --- a/jOOQ-meta/src/main/java/org/jooq/util/jaxb/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/util/jaxb/Database.java @@ -111,6 +111,9 @@ public class Database implements Serializable @XmlElement(defaultValue = "") @XmlJavaTypeAdapter(StringAdapter.class) protected String catalogVersionProvider = ""; + @XmlElement(defaultValue = "") + @XmlJavaTypeAdapter(StringAdapter.class) + protected String orderProvider = ""; protected Boolean tableValuedFunctions; @XmlElementWrapper(name = "properties") @XmlElement(name = "property") @@ -973,6 +976,32 @@ public class Database implements Serializable this.catalogVersionProvider = value; } + /** + * A custom {@link java.util.Comparator} that can compare two {@link org.jooq.util.Definition} objects to determine their order. + *

+ * This comparator can be used to influence the order of any object that is produced by jOOQ meta, and thus, indirectly, the order of declared objects in generated code. + * + * @return + * possible object is + * {@link String } + * + */ + public String getOrderProvider() { + return orderProvider; + } + + /** + * Sets the value of the orderProvider property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setOrderProvider(String value) { + this.orderProvider = value; + } + /** * Whether table valued functions should be reported as tables. *

@@ -1227,6 +1256,11 @@ public class Database implements Serializable return this; } + public Database withOrderProvider(String value) { + setOrderProvider(value); + return this; + } + public Database withTableValuedFunctions(Boolean value) { setTableValuedFunctions(value); return this; diff --git a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.10.0.xsd b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.10.0.xsd index cebf6ee044..93d222b68c 100644 --- a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.10.0.xsd +++ b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.10.0.xsd @@ -634,6 +634,12 @@ Catalog versions will be generated into the {@link javax.annotation.Generated} a generated artefacts.]]> + + +This comparator can be used to influence the order of any object that is produced by jOOQ meta, and thus, indirectly, the order of declared objects in generated code.]]> + +