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

io.vertx.up.commune.Envelop Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.up.commune;

import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpStatusCode;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.Session;
import io.vertx.up.commune.envelop.Rib;
import io.vertx.up.exception.WebException;
import io.vertx.up.exception.web._500InternalServerException;
import io.vertx.up.fn.Fn;
import io.vertx.zero.exception.IndexExceedException;

import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

public class Envelop implements Serializable {

    /* Basic Data for Envelop such as: Data, Error, Status */
    private final HttpStatusCode status;
    private final WebException error;
    private final JsonObject data;

    /* Additional Data for Envelop, Assist Data here. */
    private final Assist assist = new Assist();

    /* Communicate Key in Event Bus, to identify the Envelop */
    private String key;
    /*
     * Constructor for Envelop creation, two constructor for
     * 1) Success Envelop
     * 2) Failure Envelop
     * All Envelop are private mode with non-single because it's
     * Data Object instead of tool or other reference
     */

    /**
     * @param data   input data that stored into Envelop
     * @param status http status of this Envelop
     * @param     The type of stored data
     */
    private  Envelop(final T data, final HttpStatusCode status) {
        this.data = Rib.input(data);
        error = null;
        this.status = status;
    }

    /**
     * @param error input error that stored into Envelop
     */
    private Envelop(final WebException error) {
        status = error.getStatus();
        this.error = error;
        data = error.toJson();
    }

    /*
     * Static method to create new Envelop with different fast mode here.
     * 1) Success: 204 Empty Envelop ( data = null )
     * 2) Success: 200 With input data ( data = T )
     * 3) Success: XXX with input data ( data = T ) XXX means that you can have any HttpStatus
     * 4) Error: 500 Default error with description
     * 5) Error: XXX with input WebException
     * 6) Error: 500 Default with Throwable ( JVM Error )
     */
    // 204, null
    public static Envelop ok() {
        return new Envelop(null, HttpStatusCode.NO_CONTENT);
    }

    public static Envelop okJson() {
        return new Envelop(new JsonObject(), HttpStatusCode.OK);
    }

    // 200, T
    public static  Envelop success(final T entity) {
        return new Envelop(entity, HttpStatusCode.OK);
    }

    // xxx, T
    public static  Envelop success(final T entity, final HttpStatusCode status) {
        return new Envelop(entity, status);
    }

    // default error 500
    public static Envelop failure(final String message) {
        return new Envelop(new _500InternalServerException(Envelop.class, message));
    }

    // default error 500 ( JVM Error )
    public static Envelop failure(final Throwable ex) {
        return new Envelop(new _500InternalServerException(Envelop.class, ex.getMessage()));
    }

    // other error with WebException
    public static Envelop failure(final WebException error) {
        return new Envelop(Rib.normalize(error));
    }

    // ------------------ Above are initialization method -------------------
    /*
     * Predicate to check envelop to see whether is't valid
     * Error = null means valid
     */
    public boolean valid() {
        return null == error;
    }

    public WebException error() {
        return error;
    }

    // ------------------ Below are data part -------------------
    /* Get `data` part */
    public  T data() {
        return Rib.get(data);
    }

    /* Get `data` part by type */
    public  T data(final Class clazz) {
        return Rib.get(data, clazz);
    }

    /* Get `data` part by argIndex here */
    public  T data(final Integer argIndex, final Class clazz) {
        Fn.outUp(!Rib.isIndex(argIndex), IndexExceedException.class, getClass(), argIndex);
        return Rib.get(data, clazz, argIndex);
    }

    /* Set value in `data` part */
    public void setValue(final String field, final Object value) {
        Rib.set(data, field, value, null);
    }

    /* Set value in `data` part ( with Index ) */
    public void setValue(final Integer argIndex, final String field, final Object value) {
        Rib.set(data, field, value, argIndex);
    }

    // ------------------ Below are response Part -------------------
    /* String */
    public String outString() {
        return outJson().encode();
    }

    /* Json */
    public JsonObject outJson() {
        return Rib.outJson(data, error);
    }

    /* Buffer */
    public Buffer outBuffer() {
        return Rib.outBuffer(data, error);
    }

    /* Future */
    public Future toFuture() {
        return Future.succeededFuture(this);
    }

    // ------------------ Below are Bean Get -------------------
    /* HttpStatusCode */
    public HttpStatusCode status() {
        return status;
    }

    /* Communicate Id */
    public Envelop key(final String key) {
        this.key = key;
        return this;
    }

    public String key() {
        return key;
    }

    // ------------------ Below are Query part ----------------
    private void reference(final Consumer consumer) {
        final JsonObject reference = Rib.getBody(data);
        if (Objects.nonNull(reference)) {
            consumer.accept(reference);
        }
    }

    /* Query Part for projection */
    public void onProjection(final JsonArray projection) {
        reference(reference -> Rib.projection(reference, projection, false));
    }

    public void inProjection(final JsonArray projection) {
        reference(reference -> Rib.projection(reference, projection, true));
    }

    /* Query Part for criteria */
    public void onCriteria(final JsonObject criteria) {
        reference(reference -> Rib.criteria(reference, criteria, false));
    }

    public void inCriteria(final JsonObject criteria) {
        reference(reference -> Rib.criteria(reference, criteria, true));
    }

    // ------------------ Below are assist method -------------------
    /*
     * Assist Data for current Envelop, all these methods will resolve the issue
     * of EventBus splitted. Because all the request data could not be got from Worker class,
     * then the system will store some reference/data into Envelop and then after
     * this envelop passed from EventBus address, it also could keep state here.
     */
    /* Extract data from Context Map */
    public  T context(final String key, final Class clazz) {
        return assist.getContextData(key, clazz);
    }

    /* Get user data from User of Context */
    public String identifier(final String field) {
        return assist.principal(field);
    }

    public User user() {
        return assist.user();
    }

    public void setUser(final User user) {
        assist.user(user);
    }

    /* Get Headers */
    public MultiMap headers() {
        return assist.headers();
    }

    public void setHeaders(final MultiMap headers) {
        assist.headers(headers);
    }

    /* Session */
    public Session getSession() {
        return assist.session();
    }

    public void setSession(final Session session) {
        assist.session(session);
    }

    /* Uri */
    public String getUri() {
        return assist.uri();
    }

    public void setUri(final String uri) {
        assist.uri(uri);
    }

    /* Method of Http */
    public HttpMethod getMethod() {
        return assist.method();
    }

    public void setMethod(final HttpMethod method) {
        assist.method(method);
    }

    /* Context Set */
    public void setContext(final Map data) {
        assist.context(data);
    }

    /*
     * Bind Routing Context to process Assist structure
     */
    public Envelop bind(final RoutingContext context) {
        final HttpServerRequest request = context.request();

        /* Http Request Part */
        assist.headers(request.headers());
        assist.uri(request.uri());
        assist.method(request.method());

        /* Session, User, Data */
        assist.session(context.session());
        assist.user(context.user());
        assist.context(context.data());
        return this;
    }

    @Override
    public String toString() {
        return "Envelop{" +
                "status=" + status +
                ", error=" + error +
                ", data=" + data +
                ", assist=" + assist +
                ", key='" + key + '\'' +
                '}';
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy