All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.dbclient.DbClientServiceBase Maven / Gradle / Ivy

There is a newer version: 4.1.4
Show newest version
/*
 * Copyright (c) 2020, 2023 Oracle and/or its affiliates.
 *
 * 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.
 */
package io.helidon.dbclient;

import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import io.helidon.common.Builder;
import io.helidon.common.config.Config;

/**
 * A base implementation of a client service that supports configuration
 * of execution based on a statement name pattern and statement types.
 */
public abstract class DbClientServiceBase implements DbClientService {

    private final Predicate predicate;

    /**
     * Create a new instance based on the builder base each implementation must extend.
     *
     * @param builder builder to configure predicate to use
     */
    protected DbClientServiceBase(BuilderBase builder) {
        this.predicate = builder.predicate();
    }

    @Override
    public final DbClientServiceContext statement(DbClientServiceContext context) {
        if (predicate.test(context)) {
            return apply(context);
        }
        return context;
    }

    /**
     * This method is only invoked if the predicate for this service
     * was passed.
     *
     * @param context db client invocation context
     * @return single with the new context (or the same one if not modified)
     * @see #statement(io.helidon.dbclient.DbClientServiceContext)
     */
    protected abstract DbClientServiceContext apply(DbClientServiceContext context);

    /**
     * A base class for builders of {@link DbClientServiceBase}.
     *
     * @param  type of the builder extending this class
     * @param  Type of the built {@link DbClientServiceBase} instance
     */
    public abstract static class BuilderBase, T extends DbClientServiceBase>
            implements Builder {

        private static final Predicate YES = it -> true;
        private static final Predicate NO = it -> false;

        // we can filter by statement name
        private final Set statementNames = new LinkedHashSet<>();
        // and statement type
        private final Set statementTypes = EnumSet.noneOf(DbStatementType.class);
        private Predicate predicate;
        private boolean enabled = true;

        /**
         * Default constructor.
         */
        protected BuilderBase() {
        }

        /**
         * Configure this client service from config.
         * 

* Supported keys: *

* * * * * * * * * * * * * * * * * * * * * *
Database Client Service configuration options
keydefault valuedescription
statement-names An array of statement name patterns to apply this service for. If undefined, service * would be executed for all statements. * See {@link #statementNames(String...)} and {@link java.util.regex.Pattern}
statement-types An array of statement types to apply this service for. If undefined, service * would be executed for all statements. * See {@link #statementTypes(io.helidon.dbclient.DbStatementType...)}.
enabled{@code true}Whether this client service is enabled. See {@link #enabled(boolean)}
* * @param config configuration on the node of this service * @return updated builder instance */ public B config(Config config) { config.get("statement-names").asList(String.class).ifPresent(this::statementNames); config.get("statement-types").asNodeList() .ifPresent(nodes -> statementTypes(nodes.stream() .map(cfg -> DbStatementType.valueOf(cfg.asString().get())) .toList())); config.get("enabled").asBoolean().ifPresent(this::enabled); return identity(); } /** * Configure a predicate whose result will be used to decide whether to * trigger this service or not. *

* When a predicate is explicitly configured, {@link #statementNames(String...)} * and {@link #statementTypes(io.helidon.dbclient.DbStatementType...)} is ignored. * * @param predicate predicate that should return {@code true} to enable this * service, or {@code false} to disable it * @return updated builder instance */ public B statementPredicate(Predicate predicate) { this.predicate = predicate; return identity(); } /** * Configure statement types this service will be triggered for. * If an explicit {@link #statementPredicate(java.util.function.Predicate)} is configured, * this method is ignored. * * @param types types that trigger this service * @return updated builder instance */ public B statementTypes(DbStatementType... types) { return statementTypes(List.of(types)); } /** * Configure statement name patterns this service will be triggered for. * If an explicit {@link #statementPredicate(java.util.function.Predicate)} is configured, * this method is ignored. * * @param names name patterns (as in {@link java.util.regex.Pattern}) that trigger this service * @return updated builder instance */ public B statementNames(String... names) { return statementNames(List.of(names)); } /** * Configure whether this service is enabled or not. * * @param enabled whether to enable this service or disable it, {@code true} by default */ public void enabled(boolean enabled) { this.enabled = enabled; } /** * Configures statement types from configuration. * * @param types types to add for this service * @return updated builder instance */ protected B statementTypes(List types) { this.statementTypes.addAll(types); return identity(); } /** * Configures statement name patterns from configuration. * * @param names names to add for this service * @return updated builder instance */ protected B statementNames(List names) { this.statementNames.addAll(names); return identity(); } /** * Set of statement name patterns. * * @return configured statement names */ protected Set statementNames() { return statementNames; } /** * Set of statement types. * * @return configured statement types */ protected Set statementTypes() { return statementTypes; } /** * Predicate used to build a client service. *

* The predicate always returns {@code false} if service is disabled. *

* The predicate is obtained from the configured predicate using * {@link #statementPredicate(java.util.function.Predicate)}, * if none is configured, it is created from configured statement types and statement names. * If none are configured, the predicate just returns {@code true}. * * @return predicate to check whether this service should be invoked for current statement context */ protected Predicate predicate() { if (!enabled) { return NO; } if (null != predicate) { return predicate; } List namePatterns = statementNames.stream() .map(Pattern::compile) .toList(); Set types = EnumSet.copyOf(statementTypes); Predicate namePredicate; Predicate typePredicate; if (namePatterns.isEmpty()) { namePredicate = YES; } else { namePredicate = it -> { String statementName = it.statementName(); for (Pattern namePattern : namePatterns) { if (namePattern.matcher(statementName).matches()) { return true; } } return false; }; } if (types.isEmpty()) { typePredicate = YES; } else { typePredicate = it -> types.contains(it.statementType()); } return context -> namePredicate.test(context) && typePredicate.test(context); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy