diff --git a/jOOQ/src/main/java/org/jooq/RecordListener.java b/jOOQ/src/main/java/org/jooq/RecordListener.java index 57e1d180e6..957acf4449 100644 --- a/jOOQ/src/main/java/org/jooq/RecordListener.java +++ b/jOOQ/src/main/java/org/jooq/RecordListener.java @@ -37,7 +37,6 @@ */ package org.jooq; -import java.io.Serializable; import java.util.EventListener; import java.util.function.Consumer; @@ -68,7 +67,7 @@ import org.jooq.impl.CallbackRecordListener; * * @author Lukas Eder */ -public interface RecordListener extends EventListener, Serializable { +public interface RecordListener extends EventListener { /** * Called before storing an UpdatableRecord. diff --git a/jOOQ/src/main/java/org/jooq/TransactionListener.java b/jOOQ/src/main/java/org/jooq/TransactionListener.java index 0a81efe402..2398a1dd6b 100644 --- a/jOOQ/src/main/java/org/jooq/TransactionListener.java +++ b/jOOQ/src/main/java/org/jooq/TransactionListener.java @@ -49,7 +49,7 @@ import org.jooq.impl.CallbackTransactionListener; * * @author Lukas Eder */ -public interface TransactionListener extends Serializable { +public interface TransactionListener { /** * Called before {@link TransactionProvider#begin(TransactionContext)}. diff --git a/jOOQ/src/main/java/org/jooq/VisitListener.java b/jOOQ/src/main/java/org/jooq/VisitListener.java index acc153c177..af0d1b75f1 100644 --- a/jOOQ/src/main/java/org/jooq/VisitListener.java +++ b/jOOQ/src/main/java/org/jooq/VisitListener.java @@ -39,6 +39,9 @@ package org.jooq; import java.sql.PreparedStatement; import java.util.EventListener; +import java.util.function.Consumer; + +import org.jooq.impl.CallbackVisitListener; /** * A listener for {@link QueryPart} traversal events. @@ -143,4 +146,36 @@ public interface VisitListener extends EventListener { * @see Context#visit(QueryPart) */ void visitEnd(VisitContext context); + + /** + * Create a {@link VisitListener} with a {@link #onClauseStart(Consumer)} + * implementation. + */ + static CallbackVisitListener onClauseStart(Consumer onClauseStart) { + return new CallbackVisitListener().onClauseStart(onClauseStart); + } + + /** + * Create a {@link VisitListener} with a {@link #onClauseEnd(Consumer)} + * implementation. + */ + static CallbackVisitListener onClauseEnd(Consumer onClauseEnd) { + return new CallbackVisitListener().onClauseEnd(onClauseEnd); + } + + /** + * Create a {@link VisitListener} with a {@link #onVisitStart(Consumer)} + * implementation. + */ + static CallbackVisitListener onVisitStart(Consumer onVisitStart) { + return new CallbackVisitListener().onVisitStart(onVisitStart); + } + + /** + * Create a {@link VisitListener} with a {@link #onClauseStart(Consumer)} + * implementation. + */ + static CallbackVisitListener onVisitEnd(Consumer onVisitEnd) { + return new CallbackVisitListener().onVisitEnd(onVisitEnd); + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/CallbackRecordListener.java b/jOOQ/src/main/java/org/jooq/impl/CallbackRecordListener.java index 43360d1d62..4f1a8e2bc6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CallbackRecordListener.java +++ b/jOOQ/src/main/java/org/jooq/impl/CallbackRecordListener.java @@ -56,11 +56,6 @@ import org.jooq.RecordListener; */ public final class CallbackRecordListener implements RecordListener { - /** - * Generated UID - */ - private static final long serialVersionUID = -4135358887698253754L; - private final Consumer onStoreStart; private final Consumer onStoreEnd; private final Consumer onInsertStart; diff --git a/jOOQ/src/main/java/org/jooq/impl/CallbackTransactionListener.java b/jOOQ/src/main/java/org/jooq/impl/CallbackTransactionListener.java index 72bbffa81d..e56ebef1b0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CallbackTransactionListener.java +++ b/jOOQ/src/main/java/org/jooq/impl/CallbackTransactionListener.java @@ -58,11 +58,6 @@ import org.jooq.TransactionListener; */ public final class CallbackTransactionListener implements TransactionListener { - /** - * Generated UID - */ - private static final long serialVersionUID = -4135358887698253754L; - private final Consumer onBeginStart; private final Consumer onBeginEnd; private final Consumer onCommitStart; diff --git a/jOOQ/src/main/java/org/jooq/impl/CallbackVisitListener.java b/jOOQ/src/main/java/org/jooq/impl/CallbackVisitListener.java new file mode 100644 index 0000000000..d61b04b200 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/CallbackVisitListener.java @@ -0,0 +1,140 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + + +import java.util.function.Consumer; + +import org.jooq.VisitContext; +import org.jooq.VisitListener; + +/** + * A {@link VisitListener} that allows for functional composition. + *

+ * For example:

+ * VisitListener listener = VisitListener
+ *   .onVisitStart(ctx -> something())
+ *   .onVisitEnd(ctx -> something());
+ * 
+ * + * @author Lukas Eder + */ +public final class CallbackVisitListener implements VisitListener { + + private final Consumer onClauseStart; + private final Consumer onClauseEnd; + private final Consumer onVisitStart; + private final Consumer onVisitEnd; + + public CallbackVisitListener() { + this(null, null, null, null); + } + + private CallbackVisitListener( + Consumer onClauseStart, + Consumer onClauseEnd, + Consumer onVisitStart, + Consumer onVisitEnd + ) { + this.onClauseStart = onClauseStart; + this.onClauseEnd = onClauseEnd; + this.onVisitStart = onVisitStart; + this.onVisitEnd = onVisitEnd; + } + + @Override + public final void clauseStart(VisitContext context) { + if (onClauseStart != null) + onClauseStart.accept(context); + } + + @Override + public final void clauseEnd(VisitContext context) { + if (onClauseEnd != null) + onClauseEnd.accept(context); + } + + @Override + public final void visitStart(VisitContext context) { + if (onVisitStart != null) + onVisitStart.accept(context); + } + + @Override + public final void visitEnd(VisitContext context) { + if (onVisitEnd != null) + onVisitEnd.accept(context); + } + + public final CallbackVisitListener onClauseStart(Consumer newOnClauseStart) { + return new CallbackVisitListener( + newOnClauseStart, + onClauseEnd, + onVisitStart, + onVisitEnd + ); + } + + public final CallbackVisitListener onClauseEnd(Consumer newOnClauseEnd) { + return new CallbackVisitListener( + onClauseStart, + newOnClauseEnd, + onVisitStart, + onVisitEnd + ); + } + + public final CallbackVisitListener onVisitStart(Consumer newOnVisitStart) { + return new CallbackVisitListener( + onClauseStart, + onClauseEnd, + newOnVisitStart, + onVisitEnd + ); + } + + public final CallbackVisitListener onVisitEnd(Consumer newOnVisitEnd) { + return new CallbackVisitListener( + onClauseStart, + onClauseEnd, + onVisitStart, + newOnVisitEnd + ); + } +} + diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index b48f903100..c7f762305b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -55,6 +55,7 @@ import static org.jooq.SQLDialect.MYSQL; // ... // ... // ... +import static org.jooq.VisitListener.onVisitStart; import static org.jooq.conf.ParseWithMetaLookups.IGNORE_ON_FAILURE; import static org.jooq.conf.ParseWithMetaLookups.THROW_ON_FAILURE; import static org.jooq.conf.SettingsTools.parseLocale; @@ -578,6 +579,7 @@ import org.jooq.User; // ... // ... import org.jooq.VisitContext; +import org.jooq.VisitListener; import org.jooq.WindowBeforeOverStep; import org.jooq.WindowDefinition; import org.jooq.WindowFromFirstLastStep; @@ -13392,17 +13394,14 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { // [#8722] TODO Replace this by a public SPI // [#11054] Use a VisitListener to find actual Params in the expression tree, // which may have more refined DataTypes attached to them, from context - dsl.configuration().derive(new DefaultVisitListener() { - @Override - public void visitStart(VisitContext context) { - if (context.queryPart() instanceof Param) { - Param p = (Param) context.queryPart(); + dsl.configuration().derive(onVisitStart(ctx -> { + if (ctx.queryPart() instanceof Param) { + Param p = (Param) ctx.queryPart(); - if (!params.containsKey(p.getParamName())) - params.put(p.getParamName(), p); - } + if (!params.containsKey(p.getParamName())) + params.put(p.getParamName(), p); } - }).dsl().render(result); + })).dsl().render(result); for (String name : bindParams.keySet()) bindParamListener.accept(params.get(name)); diff --git a/jOOQ/src/main/java/org/jooq/impl/TranslatingMetaProvider.java b/jOOQ/src/main/java/org/jooq/impl/TranslatingMetaProvider.java index 0db052917a..9da539f76f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TranslatingMetaProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/TranslatingMetaProvider.java @@ -37,6 +37,7 @@ */ package org.jooq.impl; +import static org.jooq.VisitListener.onVisitStart; import static org.jooq.impl.DSL.name; import java.io.Reader; @@ -58,6 +59,7 @@ import org.jooq.Query; import org.jooq.ResultQuery; import org.jooq.Source; import org.jooq.VisitContext; +import org.jooq.VisitListener; import org.jooq.conf.RenderNameCase; import org.jooq.conf.Settings; import org.jooq.conf.SettingsTools; @@ -117,42 +119,39 @@ final class TranslatingMetaProvider implements MetaProvider { final RenderNameCase nameCase = settings.getRenderNameCase(); final Locale locale = SettingsTools.interpreterLocale(ctx.settings()); if (nameCase != null && nameCase != RenderNameCase.AS_IS) { - ctx.configuration().set(new DefaultVisitListener() { - @Override - public void visitStart(VisitContext c) { - if (c.queryPart() instanceof Name) { - Name[] parts = ((Name) c.queryPart()).parts(); - boolean changed = false; + ctx.configuration().set(onVisitStart(c -> { + if (c.queryPart() instanceof Name) { + Name[] parts = ((Name) c.queryPart()).parts(); + boolean changed = false; - for (int i = 0; i < parts.length; i++) { - Name replacement = parts[i]; - switch (nameCase) { - case LOWER_IF_UNQUOTED: - if (parts[i].quoted() == Quoted.QUOTED) break; - case LOWER: - replacement = DSL.quotedName(parts[i].first().toLowerCase(locale)); - break; + for (int i = 0; i < parts.length; i++) { + Name replacement = parts[i]; + switch (nameCase) { + case LOWER_IF_UNQUOTED: + if (parts[i].quoted() == Quoted.QUOTED) break; + case LOWER: + replacement = DSL.quotedName(parts[i].first().toLowerCase(locale)); + break; - case UPPER_IF_UNQUOTED: - if (parts[i].quoted() == Quoted.QUOTED) break; - case UPPER: - replacement = DSL.quotedName(parts[i].first().toUpperCase(locale)); - break; + case UPPER_IF_UNQUOTED: + if (parts[i].quoted() == Quoted.QUOTED) break; + case UPPER: + replacement = DSL.quotedName(parts[i].first().toUpperCase(locale)); + break; - default: - break; - } - if (!replacement.equals(parts[i])) { - parts[i] = replacement; - changed = true; - } + default: + break; + } + if (!replacement.equals(parts[i])) { + parts[i] = replacement; + changed = true; } - - if (changed) - c.queryPart(DSL.name(parts)); } + + if (changed) + c.queryPart(DSL.name(parts)); } - }); + })); } } catch (Exception e) {