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

net.binis.codegen.tools.Functional Maven / Gradle / Ivy

There is a newer version: 1.2.22
Show newest version
package net.binis.codegen.tools;

/*-
 * #%L
 * code-generator-core
 * %%
 * Copyright (C) 2021 - 2024 Binis Belev
 * %%
 * 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.
 * #L%
 */

import net.binis.codegen.annotation.Default;
import net.binis.codegen.factory.CodeFactory;

import java.util.*;
import java.util.function.*;

import static java.util.Objects.nonNull;

@SuppressWarnings("unchecked")
public class Functional {

    public static  FunctionalDoWhile _do() {
        return CodeFactory.create(FunctionalDoWhile.class);
    }

    public static  FunctionalDoWhile _do(Supplier supplier) {
        return _do()._with((Supplier) supplier);
    }

    public static  FunctionalRecursive _recursive(T start) {
        return CodeFactory.create(FunctionalRecursive.class, start);
    }

    public static  FunctionalFor _for(Iterable iterable) {
        return CodeFactory.create(FunctionalFor.class, iterable);
    }

    public static  FunctionalFor _for(Iterable iterable, R initial) {
        return CodeFactory.create(FunctionalFor.class, iterable, initial);
    }


    protected Functional() {
        //Do nothing
    }

    public static class Initializer {

        public static  Supplier> listOf(Class cls) {
            return ArrayList::new;
        }

        public static  Supplier> mapOf(Class keyClass, Class valueClass) {
            return HashMap::new;
        }

        protected Initializer() {
            //Do nothing
        }

    }

    @Default("net.binis.codegen.tools.Functional$FunctionalDoWhileImpl")
    public interface FunctionalDoWhile {
        FunctionalDoWhile _run(Runnable runnable);
        FunctionalDoWhile _with(Supplier supplier);
        FunctionalEnd _while(Predicate predicate);
        FunctionalEnd _while(BooleanSupplier supplier);
    }

    @Default("net.binis.codegen.tools.Functional$FunctionalRecursiveImpl")
    public interface FunctionalRecursive {
        FunctionalRecursive _on(UnaryOperator on);
         FunctionalRecursive _init(Supplier init);
        FunctionalRecursive _init(Q init);
        void _perform(Consumer doConsumer);
        FunctionalEnd _do(UnaryOperator doOperator);
        FunctionalEnd _do(BiFunction doFunction);
        FunctionalEnd _perform(BiConsumer perform);
    }

    @Default("net.binis.codegen.tools.Functional$FunctionalForImpl")
    public interface FunctionalFor {
        R _do(BiFunction function);
        R _do(Consumer consumer);
    }

    public interface FunctionalEnd {
        void _done();
        Optional _get();
         FunctionalEnd _map(Function mapper);
        FunctionalEnd _then(Consumer consumer);
    }

    protected static class FunctionalEndImpl implements FunctionalEnd {

        protected Object result = null;

        @Override
        public void _done() {
            //Do nothing
        }

        @Override
        public Optional _get() {
            return Optional.ofNullable(result);
        }

        @Override
        public FunctionalEnd _map(Function mapper) {
            result = mapper.apply(result);
            return this;
        }

        @Override
        public FunctionalEnd _then(Consumer consumer) {
            if (nonNull(result)) {
                consumer.accept(result);
            }
            return this;
        }
    }

    protected static class FunctionalDoWhileImpl extends FunctionalEndImpl implements FunctionalDoWhile {

        protected Supplier supplier = () -> null;

        {
            CodeFactory.registerType(FunctionalDoWhile.class, FunctionalDoWhileImpl::new, null);
        }

        @Override
        public FunctionalDoWhile _run(Runnable runnable) {
            supplier = () -> {
                runnable.run();
                return null;
            };
            return this;
        }

        @Override
        public FunctionalDoWhile _with(Supplier supplier) {
            this.supplier = supplier;
            return this;
        }

        @Override
        public FunctionalEnd _while(Predicate predicate) {
            do {
                result = supplier.get();
            } while (predicate.test(result));

            return this;
        }

        @Override
        public FunctionalEnd _while(BooleanSupplier supplier) {
            return _while(r -> supplier.getAsBoolean());
        }
    }

    protected static class FunctionalRecursiveImpl extends FunctionalEndImpl implements FunctionalRecursive {

        protected UnaryOperator on = null;
        protected T object;
        protected Supplier init;

        {
            CodeFactory.registerType(FunctionalRecursive.class, p -> new FunctionalRecursiveImpl<>(p[0]), null);
        }

        protected FunctionalRecursiveImpl(T start) {
            this.object = start;
        }

        @Override
        public FunctionalRecursive _on(UnaryOperator on) {
            this.on = on;
            return this;
        }

        @Override
        public FunctionalRecursive _init(Supplier init) {
            this.init = init;
            return this;
        }

        @Override
        public FunctionalRecursive _init(Object init) {
            this.init = () -> (R) init;
            return this;
        }

        @Override
        public void _perform(Consumer doConsumer) {
            assert nonNull(on) : "_on() operator is not specified!";
            var obj = object;
            while (nonNull(obj)) {
                obj = on.apply(obj);
            }
        }

        @SuppressWarnings("unchecked")
        @Override
        public FunctionalEnd _do(UnaryOperator doOperator) {
            var obj = object;
            while (nonNull(obj)) {
                obj = doOperator.apply(obj);
            }

            result = (R) obj;

            return (FunctionalEnd) this;
        }

        @Override
        public FunctionalEnd _do(BiFunction doFunction) {
            assert nonNull(on) : "_on() operator is not specified!";
            var obj = object;
            R res = nonNull(init)? init.get() : null;
            while (nonNull(obj)) {
                res = doFunction.apply(obj, res);
                obj = on.apply(obj);
            }
            result = res;
            return this;
        }

        @Override
        public FunctionalEnd _perform(BiConsumer perform) {
            return _do((t, r) -> {
                perform.accept(t, r);
                return r;
            });
        }
    }

    protected static class FunctionalForImpl implements FunctionalFor {

        protected final Iterable iterable;
        protected R result;

        {
            CodeFactory.registerType(FunctionalFor.class, p -> new FunctionalForImpl<>((Iterable) p[0], p.length == 2 ? (R) p[1] : null), null);
        }

        protected FunctionalForImpl(Iterable iterable, R start) {
            this.iterable = iterable;
            this.result = start;
        }

        @Override
        public R _do(BiFunction function) {
            for (var i : iterable) {
                result = function.apply(i, result);
            }

            return result;
        }

        @Override
        public R _do(Consumer consumer) {
            for (var i : iterable) {
                consumer.accept(i);
            }
            return result;
        }

    }

}