alfio.model.result.Result.java Source code

Java tutorial

Introduction

Here is the source code for alfio.model.result.Result.java

Source

/**
 * This file is part of alf.io.
 *
 * alf.io is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * alf.io is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with alf.io.  If not, see <http://www.gnu.org/licenses/>.
 */
package alfio.model.result;

import alfio.model.result.ValidationResult.ErrorDescriptor;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.validation.ObjectError;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@AllArgsConstructor
@Getter
public class Result<T> {

    private final ResultStatus status;
    private final T data;
    private final List<ErrorCode> errors;

    public static <T> Result<T> success(T data) {
        return new Result<>(ResultStatus.OK, data, Collections.emptyList());
    }

    public static <T> Result<T> validationError(List<ObjectError> errors) {
        return new Result<>(ResultStatus.VALIDATION_ERROR, null,
                errors.stream().map(ErrorDescriptor::fromObjectError).collect(Collectors.toList()));
    }

    public static <T> Result<T> error(List<ErrorCode> errorDescriptors) {
        return new Result<>(ResultStatus.ERROR, null, errorDescriptors);
    }

    public static <T> Result<T> error(ErrorCode errorDescriptor) {
        return error(Collections.singletonList(errorDescriptor));
    }

    public boolean isSuccess() {
        return status == ResultStatus.OK;
    }

    public void ifSuccess(Consumer<T> consumer) {
        if (isSuccess()) {
            consumer.accept(data);
        }
    }

    public <K> Result<K> map(Function<T, K> mapper) {
        if (isSuccess()) {
            return Result.success(mapper.apply(data));
        }
        return Result.error(this.errors);
    }

    public <K> Result<K> flatMap(Function<T, Result<K>> mapper) {
        if (isSuccess()) {
            return Objects.requireNonNull(mapper.apply(data), "this method does not allow null values");
        }
        return Result.error(this.errors);
    }

    public ErrorCode getFirstErrorOrNull() {
        if (isSuccess() || CollectionUtils.size(errors) == 0) {
            return null;
        }
        return errors.get(0);
    }

    public enum ResultStatus {
        OK, VALIDATION_ERROR, ERROR
    }

    public static final class Builder<T> {
        private final List<Pair<ConditionValidator, ErrorCode>> validators = new ArrayList<>();

        public Builder() {
        }

        public Builder<T> checkPrecondition(ConditionValidator validator, ErrorCode error) {
            this.validators.add(Pair.of(validator, error));
            return this;
        }

        public Result<T> build(Supplier<T> valueSupplier) {
            Optional<Pair<ConditionValidator, ErrorCode>> validationError = this.validators.stream()
                    .filter(p -> !p.getLeft().isValid()).findFirst();
            return validationError.map(p -> Result.<T>error(Collections.singletonList(p.getRight())))
                    .orElseGet(() -> Result.success(valueSupplier.get()));
        }

    }

    public static <T> Result<T> fromNullable(T nullable, ErrorCode justInCase) {
        if (nullable == null) {
            return Result.error(justInCase);
        }
        return Result.success(nullable);
    }

    @FunctionalInterface
    public interface ConditionValidator {
        boolean isValid();
    }
}