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

org.tools4j.nobark.loop.ComposableStep Maven / Gradle / Ivy

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.tools4j.nobark.loop;

import java.util.Objects;

/**
 * Extension of {@link Step} with enhanced functionality facilitating the composition of step chains.
 */
@FunctionalInterface
public interface ComposableStep extends Step {

    /**
     * Returns a composable step that performs first this and then the next step.
     * 

* The procedure eliminates {@link #NO_OP no-OP} steps, i.e. it returns this if * (next == NO_OP). * * @param next the next step to be performed after this * @return a composite step performing this and then next */ default ComposableStep then(final Step next) { Objects.requireNonNull(next); return next == NO_OP ? this : () -> perform() | next.perform(); } /** * Returns a composable step that performs first this step and then the next step * only if the first performed any work as indicated by result of the {@link #perform()} invocation. *

* The procedure eliminates {@link #NO_OP no-OP} steps, i.e. it returns this if * (next == NO_OP). * * @param next the next step to be performed after this only if it performed some work * @return a composite step performing this, and if some work was performed subsequently also * next */ default ComposableStep thenIfPerformed(final Step next) { Objects.requireNonNull(next); return next == NO_OP ? this : () -> perform() && (true | next.perform());//NOTE: true is needed for correctness } /** * Returns a composable step that performs first this step and then the next step * only if the first performed no work as indicated by result of the {@link #perform()} invocation. *

* The procedure eliminates {@link #NO_OP no-OP} steps, i.e. it returns this if * (next == NO_OP). * * @param next the next step to be performed after this only if it performed no work * @return a composite step performing this, and if no work was performed subsequently * next */ default ComposableStep thenIfNotPerformed(final Step next) { Objects.requireNonNull(next); return next == NO_OP ? this : () -> perform() || next.perform(); } /** * Returns a composable step given a "normal" step. *

* The procedure preserves {@link #NO_OP no-OP} steps as well as existing instances of {@code ComposableStep}, * which means that such values are returned unchanged. * * @param step the step to be wrapped as a {@code ComposableStep} * @return a {@code ComposableStep} doing exactly the same work as step but with a richer interface * for step coposition */ static ComposableStep create(final Step step) { Objects.requireNonNull(step); return step == NO_OP ? NO_OP : (step instanceof ComposableStep ? (ComposableStep)step : step::perform); } /** * Returns a step that runs all given component steps; the {@link #perform()} method of the resulting composite * step returns true if any of the component steps returns true. The procedure uses {@link #then(Step)} for the * composition and eliminates {@link #NO_OP no-OP} components. * * @param components the component steps forming the parts of the returned step * @return a new step that performs all component steps * @see #NO_OP */ static ComposableStep composite(final Step... components) { Objects.requireNonNull(components); ComposableStep result = NO_OP; for (final Step component : components) { result = result.then(component); } return result; } /** * Step performing a no-OP; the implementation returns false indicating that no work was performed. All composition * methods are optimised to eliminate no-OP steps. */ ComposableStep NO_OP = new ComposableStep() { @Override public boolean perform() { return false; } @Override public ComposableStep then(final Step next) { return ComposableStep.create(next); } @Override public ComposableStep thenIfPerformed(final Step next) { Objects.requireNonNull(next); return NO_OP; } @Override public ComposableStep thenIfNotPerformed(final Step next) { return ComposableStep.create(next); } }; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy