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

io.vertx.up.uca.rs.validation.Validator Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.up.uca.rs.validation;

import io.reactivex.Observable;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.up.atom.Rule;
import io.vertx.up.atom.agent.Depot;
import io.vertx.up.atom.agent.Event;
import io.vertx.up.eon.ID;
import io.vertx.up.eon.Strings;
import io.vertx.up.exception.WebException;
import io.vertx.up.exception.web._400ValidationException;
import io.vertx.up.runtime.ZeroCodex;
import io.vertx.up.util.Ut;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.executable.ExecutableValidator;
import javax.ws.rs.BodyParam;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class Validator {

    private static final javax.validation.Validator VALIDATOR
            = Validation.buildDefaultValidatorFactory().usingContext().messageInterpolator(
            new ValidatorInterpolator()
    ).getValidator();

    private static final ConcurrentMap>>
            RULERS = new ConcurrentHashMap<>();

    private static Validator INSTANCE;

    public static Validator create() {
        if (null == INSTANCE) {
            synchronized (Validator.class) {
                if (null == INSTANCE) {
                    INSTANCE = new Validator();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * Validate the method parameters based on javax.validation: Hibernate Validator.
     *
     * @param proxy  The checked target object.
     * @param method The checked target method.
     * @param args   The checked target method's parameters.
     * @param     The target object type: Generic types.
     */
    public  void verifyMethod(
            final T proxy,
            final Method method,
            final Object[] args) {
        // 1. Get method validator
        final ExecutableValidator validatorParam
                = VALIDATOR.forExecutables();
        // 2. Create new params that wait for validation
        final Set> constraints
                = validatorParam.validateParameters(proxy, method, args);
        // 3. Throw out exception
        if (!constraints.isEmpty()) {
            final ConstraintViolation item = constraints.iterator().next();
            replyError(proxy, method, item);
        }
    }

    private  void replyError(final T proxy, final Method method,
                                final ConstraintViolation item) {
        if (null != item) {
            final WebException error
                    = new _400ValidationException(getClass(),
                    proxy.getClass(), method, item.getMessage());
            error.setReadible(item.getMessage());
            throw error;
        }
    }

    /**
     * Advanced ruler building for Body content validation based on yml configuration.
     *
     * @param depot The container to contains event, configuration, ruler.
     * @return The configured rulers.
     */
    public Map> buildRulers(
            final Depot depot) {
        final Map> rulers
                = new LinkedHashMap<>();
        final ConcurrentMap>
                annotions = depot.getAnnotations();
        Observable.fromIterable(annotions.keySet())
                .filter(ID.DIRECT::equals)
                .map(annotions::get)
                // 1. Check whether contains @BodyParam
                .any(item -> BodyParam.class == item)
                // 2. Build rulers
                .map(item -> buildKey(depot.getEvent()))
                .map(this::buildRulers)
                .subscribe(rulers::putAll).dispose();
        return rulers;
    }

    private Map> buildRulers(final String key) {
        if (RULERS.containsKey(key)) {
            return RULERS.get(key);
        } else {
            final JsonObject rule = ZeroCodex.getCodex(key);
            final Map> ruler
                    = new LinkedHashMap<>();
            if (null != rule) {
                Ut.itJObject(rule, (value, field) -> {
                    // Checked valid rule config
                    final List rulers = buildRulers(value);
                    if (!rulers.isEmpty()) {
                        ruler.put(field, rulers);
                    }
                });
                if (!ruler.isEmpty()) {
                    RULERS.put(key, ruler);
                }
            }
            return ruler;
        }
    }

    private List buildRulers(final Object config) {
        final List rulers = new ArrayList<>();
        if (config instanceof JsonArray) {
            final JsonArray configData = (JsonArray) config;
            Ut.itJArray(configData, JsonObject.class, (item, index) -> {
                final Rule ruler = Rule.create(item);
                if (null != ruler) {
                    rulers.add(ruler);
                }
            });
        }
        return rulers;
    }

    private String buildKey(final Event event) {
        String prefix = event.getPath().trim().substring(1);
        prefix = prefix.replace(Strings.SLASH, Strings.DOT);
        prefix = prefix.replace(Strings.COLON, Strings.DOLLER);
        final String suffix = event.getMethod().name().toLowerCase(Locale.getDefault());
        return prefix + Strings.DOT + suffix;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy