silentbalanceyh/vertx-zero

View on GitHub
vertx-gaia/vertx-up/src/main/web/io/vertx/up/backbone/hunt/Flower.java

Summary

Maintainability
A
1 hr
Test Coverage
package io.vertx.up.backbone.hunt;

import io.horizon.atom.common.Kv;
import io.horizon.exception.WebException;
import io.horizon.uca.log.Annal;
import io.vertx.core.Future;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.ext.web.RoutingContext;
import io.vertx.up.annotations.Codex;
import io.vertx.up.atom.Rule;
import io.vertx.up.atom.agent.Depot;
import io.vertx.up.atom.agent.Event;
import io.vertx.up.atom.container.VInstance;
import io.vertx.up.backbone.announce.Rigor;
import io.vertx.up.commune.Envelop;
import io.vertx.up.exception.web._411ContentLengthException;
import io.vertx.up.extension.dot.PluginExtension;
import io.vertx.up.secure.validation.Validator;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;

class Flower {

    private static final Annal LOGGER = Annal.get(Flower.class);

    static <T> Future<Envelop> next(final RoutingContext context,
                                    final T entity) {
        final Envelop envelop = Envelop
            .success(entity)
            .bind(context);     // Bind Data Here.
        /*
         * Extension System of:
         * 1) PlugAuditor
         * 2) PlugRegion
         */
        return PluginExtension.Flower.next(context, envelop);
    }

    static void replyError(final RoutingContext context,
                           final WebException error,
                           final Event event) {
        final Envelop envelop = Envelop.failure(error);
        Answer.reply(context, envelop, event);
    }

    static void executeRequest(final RoutingContext context,
                               final Map<String, List<Rule>> rulers,
                               final Depot depot,
                               final Object[] args,
                               final Validator verifier) {
        // Extract major object
        WebException error = verifyPureArguments(verifier, depot, args);
        if (null == error) {
            error = verifyUpload(context);
        }
        if (null == error) {
            // Check if annotated with @Codex
            final Kv<Integer, Class<?>> found = findParameter(depot.getEvent().getAction());
            if (null == found.value()) {
                // Verify here.
                context.next();
            } else {
                // @Codex validation for different types
                final Class<?> type = found.value();
                final Object value = args[found.key()];
                verifyCodex(context, rulers, depot, type, value);
            }
        } else {
            // Hibernate validate handler
            replyError(context, error, depot.getEvent());
        }
    }

    private static Kv<Integer, Class<?>> findParameter(
        final Method method) {
        int index = 0;
        final Kv<Integer, Class<?>> result = Kv.create();
        for (final Parameter parameter : method.getParameters()) {
            if (parameter.isAnnotationPresent(Codex.class)) {
                result.set(index, parameter.getType());
                break;
            }
            index++;
        }
        return result;
    }

    private static void verifyCodex(final RoutingContext context,
                                    final Map<String, List<Rule>> rulers,
                                    final Depot depot,
                                    final Class<?> type,
                                    final Object value) {
        final Rigor rigor = Rigor.get(type);
        if (null == rigor) {
            LOGGER.warn(INFO.RIGOR_NOT_FOUND, type);
            context.next();
        } else {
            final WebException error = rigor.verify(rulers, value);
            if (null == error) {
                // Ignore Errors
                context.next();
            } else {
                // Reply Error
                replyError(context, error, depot.getEvent());
            }
        }
    }

    private static WebException verifyPureArguments(
        final Validator verifier,
        final Depot depot,
        final Object[] args) {
        final Event event = depot.getEvent();
        final Object proxy = event.getProxy();
        final Method method = event.getAction();
        WebException error = null;
        try {
            final Object delegate;
            if (proxy instanceof VInstance) {
                // Validation for dynamic proxy
                final VInstance vInstance = (VInstance) proxy;
                delegate = vInstance.proxy();
            } else {
                // Validation for proxy
                delegate = proxy;
            }
            verifier.verifyMethod(delegate, method, args);
        } catch (final WebException ex) {
            // Basic validation handler
            error = ex;
        }
        return error;
    }

    private static WebException verifyUpload(final RoutingContext context) {
        final HttpServerRequest request = context.request();
        if (request.isExpectMultipart()) {
            if (!request.headers().contains(HttpHeaders.CONTENT_LENGTH)) {
                /*
                 * Content-Length = 0
                 */
                return new _411ContentLengthException(Flower.class, 0);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }
}