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

net.diversionmc.error.Results Maven / Gradle / Ivy

There is a newer version: 1.29.2
Show newest version
package net.diversionmc.error;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collector;

import static java.util.Collections.unmodifiableList;
import static net.diversionmc.error.Functionals.applyF;
import static net.diversionmc.error.Result.*;

/**
 * Results represents collected oks and errors from a {@link Result} stream.
 *
 * @param  Success type
 * @param  Error type
 */
public class Results {
    private final List oks = new ArrayList<>();
    private final List errors = new ArrayList<>();

    /**
     * Immutably combine two results into one.
     *
     * @param other Other results to combine with this.
     * @return New collected results.
     */
    public Results combine(Results other) {
        var res = new Results();
        res.oks.addAll(oks);
        res.oks.addAll(other.oks);
        res.errors.addAll(errors);
        res.errors.addAll(other.errors);
        return res;
    }

    /**
     * Get all successful results values.
     *
     * @return List of oks.
     */
    public List oks() {
        return unmodifiableList(oks);
    }

    /**
     * Get all unsuccessful results values.
     *
     * @return List of errors.
     */
    public List errors() {
        return unmodifiableList(errors);
    }

    /**
     * Displays all successful and unsuccessful values.
     *
     * @return {oks, errors}
     */
    public String toString() {
        return "{%s, %s}".formatted(oks, errors);
    }

    /**
     * Collect results to two lists: successful results, and error results.
     *
     * @param  Success type.
     * @param  Error type.
     * @return Separated results into oks and errors.
     */
    public static  Collector, ?, Results> toResults() {
        return Collector.of(
            Results::new,
            (results, result) -> result
                .peekOk(results.oks::add)
                .peekError(results.errors::add),
            Results::combine);
    }

    /**
     * Try to parse a boolean.
     *
     * @param s String to parse.
     * @return Result of {@link Boolean#parseBoolean(String)}.
     */
    public static Result parseBoolean(String s) {
        return ok(Boolean.parseBoolean(s));
    }

    /**
     * Try to parse a byte.
     *
     * @param s String to parse.
     * @return Result of {@link Byte#parseByte(String)}.
     */
    public static Result parseByte(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Byte::parseByte, s)));
    }

    /**
     * Try to parse a short.
     *
     * @param s String to parse.
     * @return Result of {@link Short#parseShort(String)}.
     */
    public static Result parseShort(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Short::parseShort, s)));
    }

    /**
     * Try to parse a character.
     *
     * @param s String to parse.
     * @return Result of charAt via length 1 string.
     */
    public static Result parseCharacter(String s) {
        return s.length() == 1
            ? ok(s.charAt(0))
            : error(new NumberFormatException("For input string: \\\"%s\\\"".formatted(s)));
    }

    /**
     * Try to parse a int.
     *
     * @param s String to parse.
     * @return Result of {@link Integer#parseInt(String)}.
     */
    public static Result parseInt(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Integer::parseInt, s)));
    }

    /**
     * Try to parse a long.
     *
     * @param s String to parse.
     * @return Result of {@link Long#parseLong(String)}.
     */
    public static Result parseLong(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Long::parseLong, s)));
    }

    /**
     * Try to parse a float.
     *
     * @param s String to parse.
     * @return Result of {@link Float#parseFloat(String)}.
     */
    public static Result parseFloat(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Float::parseFloat, s)));
    }

    /**
     * Try to parse a double.
     *
     * @param s String to parse.
     * @return Result of {@link Double#parseDouble(String)}.
     */
    public static Result parseDouble(String s) {
        return tryGet(
            NumberFormatException.class,
            TryS.of(applyF(Double::parseDouble, s)));
    }

    private static final int UUID_TRIMMED_LENGTH = 32;
    private static final Pattern STRING_PATTERN
        = Pattern.compile("(.{8})(.{4})(.{4})(.{4})(.{12})");

    /**
     * Try to parse a UUID.
     *
     * @param s UUID to parse.
     * @return Result of {@link UUID#fromString(String)}
     * + attempt to parse a trimmed (dash-less) UUID.
     */
    public static Result parseUUID(String s) {
        return tryGet(
            IllegalArgumentException.class,
            TryS.of(applyF(
                UUID::fromString,
                s.length() == UUID_TRIMMED_LENGTH
                    ? STRING_PATTERN
                    .matcher(s)
                    .replaceAll("$1-$2-$3-$4-$5")
                    : s)));
    }
}