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

cn.allbs.hj212.core.SingleCharMatch 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.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 功能:
 *
 * @author chenQi
 */
public class SingleCharMatch implements ReaderMatch, ParentStream, Character> {

    private ParentStream parentStream;
    private PushbackReader reader;
    private Map, SupplierWithThrowable, IOException>> map;
    private MapEntryStepGenerator, SupplierWithThrowable, IOException>> generator;

    public SingleCharMatch(ParentStream parentStream) {
        this.parentStream = parentStream;
        this.reader = parentStream.reader();
        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 SingleCharMatch when(Predicate predicate) {
        generator.putKey(predicate);
        return this;
    }

    /**
     * 当字符一致时
     *
     * @param character 字符
     * @return THIS
     */
    public SingleCharMatch when(int character) {
        generator.putKey((c) -> c == character);
        return this;
    }

    /**
     * 当字符一致时
     *
     * @param character 字符
     * @return THIS
     */
    public SingleCharMatch when(Character character) {
        generator.putKey((c) -> c == character);
        return this;
    }

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

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

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

    public SingleCharMatch skip() {
        generator.putValue(() -> 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;
    }

    @Override
    public Optional match() throws IOException {
        int i = reader.read();
        Character character = (char) i;

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

        if (r.isPresent() &&
                r.get().get().isPresent()) {
            //必须运行成功才不会回滚
            return Optional.of(character);
        }
//        if(r.isPresent()){
//            r.get().get();
//            //TODO 必须运行成功才不会回滚
//            return Optional.of(character);
//        }
        reader.unread(i);
        return Optional.empty();
    }

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