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

rt.pipeline.pipe.PipeContext Maven / Gradle / Ivy

The newest version!
package rt.pipeline.pipe;

import com.google.common.base.Objects;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.xtend.lib.annotations.Accessors;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.Pure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rt.async.pubsub.IMessageBus;
import rt.async.pubsub.Message;
import rt.pipeline.IComponent;
import rt.pipeline.UserInfo;
import rt.pipeline.pipe.PipeResource;
import rt.pipeline.pipe.Pipeline;

@SuppressWarnings("all")
public class PipeContext {
  private final static Logger logger = LoggerFactory.getLogger("PIPELINE");
  
  @Accessors
  private final Message message;
  
  @Accessors
  private final PipeResource resource;
  
  private boolean inFail = false;
  
  private final Pipeline pipeline;
  
  private final Iterator iter;
  
  private final HashMap, Object> objects = new HashMap, Object>();
  
  public IMessageBus bus() {
    return this.pipeline.getMb();
  }
  
  public Object object(final Class type, final Object instance) {
    return this.objects.put(type, instance);
  }
  
  public  T object(final Class type) {
    Object _get = this.objects.get(type);
    return ((T) _get);
  }
  
  PipeContext(final Pipeline pipeline, final PipeResource resource, final Message message, final Iterator iter) {
    this.pipeline = pipeline;
    this.resource = resource;
    this.message = message;
    this.iter = iter;
  }
  
  /**
   * Sends the context to the delivery destination. Normally this methods is called in the end of the pipeline process.
   *  So most of the time there is no need to call this.
   */
  public void deliver() {
    if ((!this.inFail)) {
      try {
        boolean _equals = Objects.equal(this.message.typ, Message.REPLY);
        if (_equals) {
          this.deliverReply();
        } else {
          this.deliverRequest();
        }
      } catch (final Throwable _t) {
        if (_t instanceof RuntimeException) {
          final RuntimeException ex = (RuntimeException)_t;
          ex.printStackTrace();
          boolean _notEquals = (!Objects.equal(this.message.typ, Message.PUBLISH));
          if (_notEquals) {
            this.fail(ex);
          }
        } else {
          throw Exceptions.sneakyThrow(_t);
        }
      }
    }
  }
  
  /**
   * Used by interceptors, order the pipeline to execute the next interceptor. If no other interceptor exits, a delivery is proceed.
   */
  public void next() {
    if ((!this.inFail)) {
      boolean _hasNext = this.iter.hasNext();
      if (_hasNext) {
        try {
          IComponent _next = this.iter.next();
          _next.apply(this);
        } catch (final Throwable _t) {
          if (_t instanceof RuntimeException) {
            final RuntimeException ex = (RuntimeException)_t;
            ex.printStackTrace();
            this.fail(ex);
          } else {
            throw Exceptions.sneakyThrow(_t);
          }
        }
      } else {
        this.deliver();
      }
    }
  }
  
  /**
   * Send a message to the client resource
   * @param msg Should be a new message to send
   */
  public void send(final Message msg) {
    if ((!this.inFail)) {
      this.resource.send(msg);
    }
  }
  
  /**
   * Interrupts the pipeline flow and sends an error message back to the original "from". After this, other calls to "next()" or "fail(..)" are useless.
   * @param from The address that will be on reply "header.from".
   * @param error The error descriptor message.
   */
  public void fail(final Throwable ex) {
    if ((!this.inFail)) {
      this.replyError(ex);
      this.pipeline.fail(ex);
      this.inFail = true;
    }
  }
  
  /**
   * Does nothing to the pipeline flow and sends a reply back.
   * @param reply Should be a new PipeMessage
   */
  public void reply(final Message reply) {
    if ((!this.inFail)) {
      final Procedure1 _function = (Message it) -> {
        it.id = this.message.id;
        it.clt = this.message.clt;
        it.typ = Message.REPLY;
      };
      ObjectExtensions.operator_doubleArrow(reply, _function);
      this.resource.send(reply);
    }
  }
  
  /**
   * Does nothing to the pipeline flow and sends a OK reply back with a pre formatted JSON schema.
   */
  public void replyOK() {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_OK;
      };
      final Message reply = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.reply(reply);
    }
  }
  
  /**
   * Does nothing to the pipeline flow and sends a OK reply back with a pre formatted JSON schema.
   * @param value The address that will be on "from".
   */
  public void replyOK(final Object resultObj) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_OK;
        it.setResult(resultObj);
      };
      final Message reply = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.reply(reply);
    }
  }
  
  public void replyObservable(final String uuid) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_OBSERVABLE;
        it.setResult(("evt:" + uuid));
      };
      final Message reply = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.reply(reply);
    }
  }
  
  /**
   * Does nothing to the pipeline flow and sends a ERROR reply back with a pre formatted JSON schema.
   * @param value The error descriptor message.
   */
  public void replyError(final Throwable ex) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_ERROR;
        it.setResult(ex);
      };
      final Message reply = ObjectExtensions.operator_doubleArrow(_message, _function);
      PipeContext.logger.error("REPLY-ERROR {}", ex);
      this.reply(reply);
    }
  }
  
  public void publish(final Message pub) {
    if ((!this.inFail)) {
      final Procedure1 _function = (Message it) -> {
        it.clt = this.message.clt;
        it.typ = Message.PUBLISH;
      };
      ObjectExtensions.operator_doubleArrow(pub, _function);
      this.resource.send(pub);
    }
  }
  
  public void publishNext(final String uuid, final Object resultObj) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_OK;
        it.path = ("evt:" + uuid);
        it.setResult(resultObj);
      };
      final Message pub = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.publish(pub);
    }
  }
  
  public void publishComplete(final String uuid) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_COMPLETE;
        it.path = ("evt:" + uuid);
      };
      final Message pub = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.publish(pub);
    }
  }
  
  public void publishError(final String uuid, final Throwable ex) {
    if ((!this.inFail)) {
      Message _message = new Message();
      final Procedure1 _function = (Message it) -> {
        it.cmd = Message.CMD_ERROR;
        it.path = ("evt:" + uuid);
        it.setResult(ex);
      };
      final Message pub = ObjectExtensions.operator_doubleArrow(_message, _function);
      this.publish(pub);
    }
  }
  
  /**
   * Order the underlying resource channel to disconnect. But the client can be configured to reconnect, so most of the times a reconnection is made by the client.
   * To avoid this, the method should only be used when the client orders the disconnection.
   */
  public void disconnect() {
    this.resource.disconnect();
  }
  
  private void deliverRequest() {
    final UserInfo user = this.object(UserInfo.class);
    boolean _isAuthorized = this.pipeline.isAuthorized(this.message, user);
    boolean _not = (!_isAuthorized);
    if (_not) {
      PipeContext.logger.error("Authorization failed on {}", this.message.path);
      RuntimeException _runtimeException = new RuntimeException("Unauthorized user!");
      this.fail(_runtimeException);
      return;
    }
    final IComponent srv = this.pipeline.getComponent(this.message.path);
    boolean _notEquals = (!Objects.equal(srv, null));
    if (_notEquals) {
      PipeContext.logger.debug("DELIVER {}", this.message.path);
      srv.apply(this);
    } else {
      PipeContext.logger.info("PUBLISH {}", this.message.path);
      IMessageBus _mb = this.pipeline.getMb();
      _mb.publish(this.message.path, this.message);
    }
  }
  
  private void deliverReply() {
    PipeContext.logger.debug("DELIVER-REPLY {} {}", this.message.clt, this.message.id);
    IMessageBus _mb = this.pipeline.getMb();
    _mb.reply(this.message);
  }
  
  @Pure
  public Message getMessage() {
    return this.message;
  }
  
  @Pure
  public PipeResource getResource() {
    return this.resource;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy