From a85679c81527527c09ccdeb14d5e5992149368d7 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 17 Jan 2024 11:01:47 +0100 Subject: [PATCH] [jOOQ/jOOQ#10776] Add GeneratorStrategy::getJavaMemberOverride, getJavaSetterOverride, getJavaGetterOverride, getJavaMethodOverride --- .../AbstractDelegatingGeneratorStrategy.java | 20 +++++++ .../codegen/DefaultGeneratorStrategy.java | 20 +++++++ .../org/jooq/codegen/GeneratorStrategy.java | 32 +++++++++++ .../java/org/jooq/codegen/JavaGenerator.java | 56 ++++++++++++------- 4 files changed, 108 insertions(+), 20 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/AbstractDelegatingGeneratorStrategy.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/AbstractDelegatingGeneratorStrategy.java index 36a33d0582..ef34e8509d 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/AbstractDelegatingGeneratorStrategy.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/AbstractDelegatingGeneratorStrategy.java @@ -165,6 +165,26 @@ public abstract class AbstractDelegatingGeneratorStrategy extends AbstractGenera return delegate.getJavaClassImplements(definition, mode); } + @Override + public boolean getJavaGetterOverride(Definition definition, Mode mode) { + return delegate.getJavaGetterOverride(definition, mode); + } + + @Override + public boolean getJavaSetterOverride(Definition definition, Mode mode) { + return delegate.getJavaSetterOverride(definition, mode); + } + + @Override + public boolean getJavaMethodOverride(Definition definition, Mode mode) { + return delegate.getJavaMethodOverride(definition, mode); + } + + @Override + public boolean getJavaMemberOverride(Definition definition, Mode mode) { + return delegate.getJavaMemberOverride(definition, mode); + } + @Override public String getGlobalNamesJavaClassName(Definition container, Class objectType) { return delegate.getGlobalNamesJavaClassName(container, objectType); diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/DefaultGeneratorStrategy.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/DefaultGeneratorStrategy.java index 7ded0f0ad5..3122ce6c64 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/DefaultGeneratorStrategy.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/DefaultGeneratorStrategy.java @@ -289,11 +289,21 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy { return "set" + getterSetterSuffix(definition); } + @Override + public boolean getJavaSetterOverride(Definition definition, Mode mode) { + return false; + } + @Override public String getJavaGetterName(Definition definition, Mode mode) { return "get" + getterSetterSuffix(definition); } + @Override + public boolean getJavaGetterOverride(Definition definition, Mode mode) { + return false; + } + @Override public String getJavaMethodName(Definition definition, Mode mode) { // [#7148] If table A references table B only once, then B is the ideal name @@ -325,6 +335,11 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy { return getJavaClassName0LC(definition, Mode.DEFAULT); } + @Override + public boolean getJavaMethodOverride(Definition definition, Mode mode) { + return false; + } + @Override public String getGlobalNamesJavaClassExtends(Definition container, Class objectType) { return null; @@ -629,6 +644,11 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy { return getJavaClassName0LC(definition, mode); } + @Override + public boolean getJavaMemberOverride(Definition definition, Mode mode) { + return false; + } + private String getJavaClassName0LC(Definition definition, Mode mode) { String result = getJavaClassName0(definition, mode); return result.substring(0, 1).toLowerCase(targetLocale) + result.substring(1); diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/GeneratorStrategy.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/GeneratorStrategy.java index 0ac16292b5..52fcdadf60 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/GeneratorStrategy.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/GeneratorStrategy.java @@ -244,6 +244,14 @@ public interface GeneratorStrategy { */ String getJavaSetterName(Definition definition, Mode mode); + /** + * Whether the {@link #getJavaSetterName(Definition, Mode)} produces a + * method that overrides a member from a parent type unknown to jOOQ, e.g. + * from {@link #getJavaClassExtends(Definition, Mode)} or + * {@link #getJavaClassImplements(Definition, Mode)}. + */ + boolean getJavaSetterOverride(Definition definition, Mode mode); + /** * This is applied to definitions that can result in getters of a container. * For example, the definition could be a {@link ColumnDefinition}, the @@ -271,6 +279,14 @@ public interface GeneratorStrategy { */ String getJavaGetterName(Definition definition, Mode mode); + /** + * Whether the {@link #getJavaGetterName(Definition, Mode)} produces a + * method that overrides a member from a parent type unknown to jOOQ, e.g. + * from {@link #getJavaClassExtends(Definition, Mode)} or + * {@link #getJavaClassImplements(Definition, Mode)}. + */ + boolean getJavaGetterOverride(Definition definition, Mode mode); + /** * This is applied to definitions that can result in methods. For example, * the definition could be a {@link RoutineDefinition} @@ -290,6 +306,14 @@ public interface GeneratorStrategy { */ String getJavaMethodName(Definition definition, Mode mode); + /** + * Whether the {@link #getJavaMethodName(Definition, Mode)} produces a + * method that overrides a member from a parent type unknown to jOOQ, e.g. + * from {@link #getJavaClassExtends(Definition, Mode)} or + * {@link #getJavaClassImplements(Definition, Mode)}. + */ + boolean getJavaMethodOverride(Definition definition, Mode mode); + /** * @return The super class name of the global names class for a given * definition type, e.g. [com.example.AbstractPojo]. If this returns @@ -443,6 +467,14 @@ public interface GeneratorStrategy { */ String getJavaMemberName(Definition definition, Mode mode); + /** + * Whether the {@link #getJavaMemberName(Definition, Mode)} produces a + * member that overrides a member from a parent type unknown to jOOQ, e.g. + * from {@link #getJavaClassExtends(Definition, Mode)} or + * {@link #getJavaClassImplements(Definition, Mode)}. + */ + boolean getJavaMemberOverride(Definition definition, Mode mode); + /** * @return The full Java class name of the global names class for a * given definition type, e.g. [org.jooq.generated.TableNames] diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java index 412fafa7c2..130296dd75 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -2631,7 +2631,9 @@ public class JavaGenerator extends AbstractGenerator { final boolean isUDT = column.getType(resolver(out)).isUDT(); final boolean isArray = column.getType(resolver(out)).isArray(); final boolean isUDTArray = column.getType(resolver(out)).isUDTArray(); - final boolean override = generateInterfaces() && !generateImmutableInterfaces() && !isUDT; + final boolean override = generateInterfaces() && !generateImmutableInterfaces() && !isUDT + || !kotlin && getStrategy().getJavaSetterOverride(column, Mode.RECORD) + || kotlin && getStrategy().getJavaMemberOverride(column, Mode.POJO); // We cannot have covariant setters for arrays because of type erasure if (!(generateInterfaces() && isArray)) { @@ -2639,7 +2641,7 @@ public class JavaGenerator extends AbstractGenerator { out.javadoc("Setter for %s.[[before= ][%s]]", name, list(escapeEntities(comment(column)))); if (scala) { - out.println("%sdef %s(value: %s): %s = {", visibility(override), setter, type, setterReturnType); + out.println("%s%sdef %s(value: %s): %s = {", visibility(override), override ? "override " : "", setter, type, setterReturnType); out.println("set(%s, value)", index); if (generateFluentSetters()) @@ -2656,7 +2658,7 @@ public class JavaGenerator extends AbstractGenerator { printValidationAnnotation(out, column); printKotlinSetterAnnotation(out, column, Mode.RECORD); - out.println("%sopen %svar %s: %s%s", visibility(generateInterfaces()), (generateInterfaces() ? "override " : ""), member, type, kotlinNullability(out, column, Mode.RECORD)); + out.println("%sopen %svar %s: %s%s", visibility(generateInterfaces()), (override || generateInterfaces() ? "override " : ""), member, type, kotlinNullability(out, column, Mode.RECORD)); out.tab(1).println("set(value): %s = set(%s, value)", setterReturnType, index); } else { @@ -2751,17 +2753,19 @@ public class JavaGenerator extends AbstractGenerator { final String typeFull = getStrategy().getFullJavaClassName(embeddable, generateInterfaces() ? Mode.INTERFACE : Mode.RECORD); final String type = out.ref(typeFull); final String name = embeddable.getQualifiedOutputName(); - final boolean override = generateInterfaces() && !generateImmutableInterfaces(); + final boolean override = generateInterfaces() && !generateImmutableInterfaces() + || !kotlin && getStrategy().getJavaMemberOverride(embeddable, Mode.POJO) + || kotlin && getStrategy().getJavaSetterOverride(embeddable, Mode.RECORD); if (!kotlin && !printDeprecationIfUnknownType(out, typeFull)) out.javadoc("Setter for the embeddable %s.", name); if (scala) { - out.println("%sdef %s(value: %s): %s = {", visibility(override), setter, type, setterReturnType); + out.println("%s%sdef %s(value: %s): %s = {", visibility(override), override ? "override " : "", setter, type, setterReturnType); } else if (kotlin) { out.println(); - out.println("%sopen %svar %s: %s", visibility(generateInterfaces()), (generateInterfaces() ? "override " : ""), member, type); + out.println("%sopen %svar %s: %s", visibility(generateInterfaces()), (generateInterfaces() || override ? "override " : ""), member, type); out.tab(1).println("set(value): %s {", setterReturnType); } else { @@ -2844,10 +2848,12 @@ public class JavaGenerator extends AbstractGenerator { } printNullableOrNonnullAnnotation(out, column); - boolean override = generateInterfaces(); + boolean override = generateInterfaces() + || !kotlin && getStrategy().getJavaGetterOverride(column, Mode.RECORD) + || kotlin && getStrategy().getJavaMemberOverride(column, Mode.POJO); if (scala) { - out.println("%sdef %s: %s = get(%s).asInstanceOf[%s]", visibility(override), scalaWhitespaceSuffix(getter), type, index, type); + out.println("%s%sdef %s: %s = get(%s).asInstanceOf[%s]", visibility(override), override ? "override " : "", scalaWhitespaceSuffix(getter), type, index, type); } else if (kotlin) { String nullable = column instanceof EmbeddableDefinition ? "" : kotlinNullability(out, column, Mode.RECORD); @@ -5511,6 +5517,7 @@ public class JavaGenerator extends AbstractGenerator { forEach(getTypedElements(tableUdtOrEmbeddable), (column, separator) -> { final String member = getStrategy().getJavaMemberName(column, Mode.POJO); final String nullability = kotlinNullability(out, column, Mode.POJO); + final boolean override = getStrategy().getJavaMemberOverride(column, Mode.POJO); if (column instanceof ColumnDefinition) printColumnJPAAnnotation(out, (ColumnDefinition) column); @@ -5521,7 +5528,7 @@ public class JavaGenerator extends AbstractGenerator { out.println("%s%s%s %s: %s%s%s%s", visibility(generateInterfaces()), - generateInterfaces() ? "override " : "", + generateInterfaces() || override ? "override " : "", generateImmutablePojos() ? "val" : "var", member, out.ref(getJavaType(column.getType(resolver(out, Mode.POJO)), out, Mode.POJO)), @@ -5800,6 +5807,9 @@ public class JavaGenerator extends AbstractGenerator { final String columnGetter = getStrategy().getJavaGetterName(embeddable, Mode.POJO); final String columnMember = getStrategy().getJavaMemberName(embeddable, Mode.POJO); final String name = embeddable.getQualifiedOutputName(); + final boolean override = generateInterfaces() + || !kotlin && getStrategy().getJavaGetterOverride(embeddable, Mode.POJO) + || kotlin && getStrategy().getJavaMemberOverride(embeddable, Mode.POJO); // Getter if (!kotlin && !printDeprecationIfUnknownType(out, columnTypeFull)) @@ -5808,19 +5818,19 @@ public class JavaGenerator extends AbstractGenerator { printNonnullAnnotation(out); if (scala) { - out.println("%sdef %s: %s = new %s(", visibility(generateInterfaces()), scalaWhitespaceSuffix(columnGetter), columnType, columnType); + out.println("%s%sdef %s: %s = new %s(", visibility(override), override ? "override " : "", scalaWhitespaceSuffix(columnGetter), columnType, columnType); } else if (kotlin) { // [#14853] The POJO property hasn't been generated in the setter, if the POJO // is immutable, as there are no setters. if (generateImmutablePojos()) - generateEmbeddablePojoProperty(out, generateImmutableInterfaces(), generateInterfaces(), columnTypeDeclared, columnMember); + generateEmbeddablePojoProperty(out, generateImmutableInterfaces(), override, columnTypeDeclared, columnMember); out.tab(1).println("get(): %s = %s(", columnTypeDeclared, columnType); } else { - out.overrideIf(generateInterfaces()); + out.overrideIf(override); out.println("%s%s %s() {", visibility(generateInterfaces()), columnType, columnGetter); out.println("return new %s(", columnType); } @@ -5891,7 +5901,9 @@ public class JavaGenerator extends AbstractGenerator { * Subclasses may override this method to provide their own pojo setters. */ protected void generateEmbeddablePojoSetter(EmbeddableDefinition embeddable, @SuppressWarnings("unused") int index, JavaWriter out) { - final boolean override = generateInterfaces() && !generateImmutableInterfaces(); + final boolean override = generateInterfaces() && !generateImmutableInterfaces() + || !kotlin && getStrategy().getJavaSetterOverride(embeddable, Mode.POJO) + || kotlin && getStrategy().getJavaMemberOverride(embeddable, Mode.POJO); final String className = getStrategy().getJavaClassName(embeddable.getReferencingTable(), Mode.POJO); final String columnTypeFull = getStrategy().getFullJavaClassName(embeddable, override ? Mode.INTERFACE : Mode.POJO); final String columnType = out.ref(columnTypeFull); @@ -5904,7 +5916,7 @@ public class JavaGenerator extends AbstractGenerator { out.javadoc("Setter for %s.", name); if (scala) { - out.println("%sdef %s(value: %s): %s = {", visibility(override), columnSetter, columnType, columnSetterReturnType); + out.println("%s%sdef %s(value: %s): %s = {", visibility(override), override ? "override " : "", columnSetter, columnType, columnSetterReturnType); } else if (kotlin) { generateEmbeddablePojoProperty(out, false, override, columnType, columnMember); @@ -7144,6 +7156,7 @@ public class JavaGenerator extends AbstractGenerator { // [#8762] Cache these calls for much improved runtime performance! for (ForeignKeyDefinition foreignKey : outboundFKs) { final String keyMethodName = out.ref(getStrategy().getJavaMethodName(foreignKey)); + final boolean keyMethodOverride = getStrategy().getJavaMethodOverride(foreignKey, Mode.DEFAULT); final String referencedTableClassName = out.ref( getStrategy().getFullJavaClassName(foreignKey.getReferencedTable()) + (generateImplicitJoinPathTableSubtypes() ? ("." + getStrategy().getJavaClassName(foreignKey.getReferencedTable(), Mode.PATH)) : "") @@ -7174,10 +7187,10 @@ public class JavaGenerator extends AbstractGenerator { ); if (scala) { - out.println("%slazy val %s: %s = { new %s(this, %s, null) }", visibility(), scalaWhitespaceSuffix(keyMethodName), referencedTableClassName, referencedTableClassName, keyFullId); + out.println("%s%slazy val %s: %s = { new %s(this, %s, null) }", visibility(), keyMethodOverride ? "override " : "", scalaWhitespaceSuffix(keyMethodName), referencedTableClassName, referencedTableClassName, keyFullId); } else if (kotlin) { - out.println("%sfun %s(): %s {", visibility(), keyMethodName, referencedTableClassName); + out.println("%s%sfun %s(): %s {", visibility(), keyMethodOverride ? "override " : "", keyMethodName, referencedTableClassName); out.println("if (!this::_%s.isInitialized)", unquotedKeyMethodName); out.println("_%s = %s(this, %s, null)", unquotedKeyMethodName, referencedTableClassName, keyFullId); out.println(); @@ -7186,11 +7199,12 @@ public class JavaGenerator extends AbstractGenerator { if (generateImplicitJoinPathsAsKotlinProperties()) { out.println(); - out.println("%sval %s: %s", visibility(), keyMethodName, referencedTableClassName); + out.println("%s%sval %s: %s", visibility(), keyMethodOverride ? "override " : "", keyMethodName, referencedTableClassName); out.tab(1).println("get(): %s = %s()", referencedTableClassName, keyMethodName); } } else { + out.overrideIf(keyMethodOverride); out.println("%s%s %s() {", visibility(), referencedTableClassName, keyMethodName); out.println("if (_%s == null)", keyMethodName); out.println("_%s = new %s(this, %s, null);", keyMethodName, referencedTableClassName, keyFullId); @@ -7222,6 +7236,7 @@ public class JavaGenerator extends AbstractGenerator { continue inboundFKLoop; } + final boolean keyMethodOverride = getStrategy().getJavaMethodOverride(foreignKey, Mode.DEFAULT); final String keyFullId = kotlin ? out.ref(getStrategy().getFullJavaIdentifier(foreignKey)) : out.ref(getStrategy().getFullJavaIdentifier(foreignKey), 2); @@ -7249,10 +7264,10 @@ public class JavaGenerator extends AbstractGenerator { ); if (scala) { - out.println("%slazy val %s: %s = { new %s(this, null, %s.getInverseKey()) }", visibility(), scalaWhitespaceSuffix(keyMethodName), referencingTableClassName, referencingTableClassName, keyFullId); + out.println("%s%slazy val %s: %s = { new %s(this, null, %s.getInverseKey()) }", visibility(), keyMethodOverride ? "override " : "", scalaWhitespaceSuffix(keyMethodName), referencingTableClassName, referencingTableClassName, keyFullId); } else if (kotlin) { - out.println("%sfun %s(): %s {", visibility(), keyMethodName, referencingTableClassName); + out.println("%s%sfun %s(): %s {", visibility(), keyMethodOverride ? "override " : "", keyMethodName, referencingTableClassName); out.println("if (!this::_%s.isInitialized)", unquotedKeyMethodName); out.println("_%s = %s(this, null, %s.inverseKey)", unquotedKeyMethodName, referencingTableClassName, keyFullId); out.println(); @@ -7261,11 +7276,12 @@ public class JavaGenerator extends AbstractGenerator { if (generateImplicitJoinPathsAsKotlinProperties()) { out.println(); - out.println("%sval %s: %s", visibility(), keyMethodName, referencingTableClassName); + out.println("%s%sval %s: %s", visibility(), keyMethodOverride ? "override " : "", keyMethodName, referencingTableClassName); out.tab(1).println("get(): %s = %s()", referencingTableClassName, keyMethodName); } } else { + out.overrideIf(keyMethodOverride); out.println("%s%s %s() {", visibility(), referencingTableClassName, keyMethodName); out.println("if (_%s == null)", keyMethodName); out.println("_%s = new %s(this, null, %s.getInverseKey());", keyMethodName, referencingTableClassName, keyFullId);