/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.core.spring; import java.util.List; import java.util.LinkedList; import org.apache.commons.lang.Validate; import org.apache.camel.model.FromDefinition; import org.apache.camel.model.MulticastDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.ToDefinition; import org.apache.camel.processor.aggregate.AggregationStrategy; import org.apache.camel.spring.CamelContextFactoryBean; import org.springframework.beans.factory.config.BeanPostProcessor; /** An event endpoint represents a name where event sources can raise events * and clients can register listeners to be notified of such events. * * This uses camel to route events. All endpoint specifications follow camel * notation. * * This class registers a new route in the camel context named katari.eventBus. * The route has a from endpoint and multicasts the events to all the * registered listeners. * * Each Event is sent synchronously, and a response is sent back to the source * of the event. The response is built aggregating the response of every * listener. */ public class EventEndpoint implements BeanPostProcessor { /** The aggregator for event responses, never null. */ private AggregationStrategy aggregationStrategy; /** The null endpoint, where the event is sent when there are no listeners. * * If null, we use the default endpoint (bean:katari.defaultEventListener). * The default is useful when the input and output of an event are of the * same type. */ private String nullUri; /** The source endpoint, never null. */ private String fromUri; /** Listener endpoints, never null. */ private List<ToDefinition> toDefinitions; /** Creates a new event endpoint. * * @param theAggregationStrategy aggregates the response of each listener. * It cannot be null. * * @param theNullUri an endpoint where the event goes when there are no * listeners. This is necessary when the output and the input of the event * are of different types. It cannot be null. * * @param sourceUri the source endpoint name. It cannot be null. * * @param listeners the list of listeners of the events raised in the * provided source endpoint. */ public EventEndpoint(final AggregationStrategy theAggregationStrategy, final String theNullUri, final String sourceUri, final List<ToDefinition> listeners) { Validate.notNull(theAggregationStrategy, "The aggregation strategy cannot be null."); Validate.notNull(theNullUri, "The null uri cannot be null."); Validate.notNull(sourceUri, "The source uri cannot be null."); Validate.notNull(listeners, "The listeners cannot be null."); aggregationStrategy = theAggregationStrategy; nullUri = theNullUri; fromUri = sourceUri; toDefinitions = listeners; } /** Creates a new event endpoint with a default null endpoint. * * The default null endpoint can be used when the input and output of the * event are of the same type. * * @param theAggregationStrategy aggregates the response of each listener. * It cannot be null. * * @param sourceUri the source endpoint name. It cannot be null. * * @param listeners the list of listeners of the events raised in the * provided source endpoint. */ public EventEndpoint(final AggregationStrategy theAggregationStrategy, final String sourceUri, final List<ToDefinition> listeners) { Validate.notNull(theAggregationStrategy, "The aggregation strategy cannot be null."); Validate.notNull(sourceUri, "The source uri cannot be null."); Validate.notNull(listeners, "The listeners cannot be null."); aggregationStrategy = theAggregationStrategy; nullUri = "bean:katari.defaultEventListener"; fromUri = sourceUri; toDefinitions = listeners; } /** {@inheritDoc} * * This implementation does nothing. */ public Object postProcessAfterInitialization(final Object bean, final String beanName) { return bean; } /** {@inheritDoc} * * Attaches the routes to the camel context named katari.eventBus. */ public Object postProcessBeforeInitialization(final Object bean, final String beanName) { if (beanName.equals("katari.eventBus")) { // From endpoint. List<FromDefinition> from = new LinkedList<FromDefinition>(); from.add(new FromDefinition(fromUri)); // To endpoints. MulticastDefinition multicast = new MulticastDefinition(); if (toDefinitions.size() != 0) { for (ToDefinition to : toDefinitions) { multicast.addOutput(to); } } else { multicast.addOutput(new ToDefinition(nullUri)); } multicast.aggregationStrategy(aggregationStrategy); // Chains everything. RouteDefinition route = new RouteDefinition(); route.setInputs(from); route.addOutput(multicast); // Adds it to the context. CamelContextFactoryBean contextFactory = (CamelContextFactoryBean) bean; contextFactory.getRoutes().add(route); return contextFactory; } else { return bean; } } }