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

cn.allbs.hj212.core.MultipleCharMatch Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
package cn.allbs.hj212.core;


import cn.allbs.hj212.lambda.RunnableWithThrowable;
import cn.allbs.hj212.lambda.SupplierWithThrowable;

import java.io.IOException;
import java.io.PushbackReader;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 功能:
 *
 * @author chenQi
 */
public class MultipleCharMatch implements ReaderMatch, ParentStream, char[]> {

    private ParentStream parentStream;
    private PushbackReader reader;
    private int count;
    private boolean alwaysRollBack = false;
    private Map, SupplierWithThrowable, IOException>> map;
    private MapEntryStepGenerator, SupplierWithThrowable, IOException>> generator;

    public MultipleCharMatch(ParentStream parentStream, int count) {
        this.parentStream = parentStream;
        this.reader = parentStream.reader();
        this.count = count;
        this.map = new LinkedHashMap<>();
        MapEntryStepGenerator.Builder, SupplierWithThrowable, IOException>> builder = MapEntryStepGenerator.builder();
        this.generator = builder.consumer((k, v) -> map.put(k, v))
                .keyDefault(() -> character -> false)
                .keyMergeOperator(Predicate::or)
                .valueMergeOperator((thisRunnable, runnable) -> () -> {
                    Optional o = thisRunnable.get();
                    if (!o.isPresent()) {
                        o = runnable.get();
                    }
                    return o;
                })
                .create();
    }

    /**
     * 当符合条件时
     *
     * @param predicate 条件
     * @return THIS
     */
    public MultipleCharMatch when(Predicate predicate) {
        generator.putKey(predicate);
        return this;
    }

    /**
     * 当字符一致时
     *
     * @param characters 字符
     * @return THIS
     */
    public MultipleCharMatch when(char... characters) {
        generator.putKey((ca) -> Arrays.equals(ca, characters));
        return this;
    }

//    public ReaderStream> when() {
//        ReaderStream> stream = new ReaderStream<>(
//                this.reader,
//                this.parentStream.bufSize() -1,
//                this);
//        generator.putKey((ca) -> {
//            try {
//                return stream.core().isPresent();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        });
//        return stream;
//    }

    public MultipleCharMatch then(Supplier exceptionSupplier) {
        generator.putValue(() -> {
            throw exceptionSupplier.get();
        });
        return this;
    }

    public MultipleCharMatch then(SupplierWithThrowable, IOException> runnable) {
        generator.putValue(runnable);
        return this;
    }

    public MultipleCharMatch then(RunnableWithThrowable runnable) {
        generator.putValue(() -> {
            runnable.run();
            return Optional.of(true);
        });
        return this;
    }

    public ReaderStream> then() {
        ReaderStream> reader = new ReaderStream<>(
                this.reader,
                this.parentStream.bufSize() - 1,
                this);
        then(reader::match);
        return reader;
    }


    @Override
    public ParentStream done() {
        generator.generate();
        return parentStream;
    }

    /**
     * 中断
     *
     */
    public ParentStream stop() {
        return done();
    }

    /**
     * 回滚
     *
     */
    public ParentStream back() {
        alwaysRollBack = true;
        return done();
    }

    @Override
    public Optional match() throws IOException {
        char[] chars = new char[count];
        //noinspection ResultOfMethodCallIgnored
        reader.read(chars);

        Optional, IOException>> r = map.entrySet().stream()
                .filter(kv -> kv.getKey().test(chars))
                .map(Map.Entry::getValue)
                .findAny();

        if (r.isPresent()) {
            if (r.get().get().isPresent() &&
                    !alwaysRollBack) {
                //必须运行成功才不会回滚
                return Optional.of(chars);
            }
        }


//        if(r.isPresent()){
//            r.get().get();
//            return Optional.of(chars);
//        }
        //回滚
        reader.unread(chars);
        return Optional.empty();
    }

    @Override
    public String toString() {
        return parentStream.toString() +
                "/" + this.getClass().getSimpleName() + "(" + map.size() + ")";
    }

}