package uk.nhs.kch.rassyeyanie.framework.route;
import java.util.Collections;
import java.util.List;
import org.apache.camel.CamelContext;
import org.apache.camel.LoggingLevel;
import org.apache.camel.component.hl7.HL7Constants;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.model.MulticastDefinition;
import org.apache.camel.model.OnExceptionDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.spring.SpringRouteBuilder;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class SequentialTransformer
extends SpringRouteBuilder
{
private List<GenericTransformRoute> transformers;
private String inboundQueue;
private String senderQueue;
private String routeName;
private String errorQueue;
private String receiverEndpoint;
private int redeliveryAttempts;
private long redeliveryDelay;
private final Logger logger;
private GenericSender sender;
private String[] workerIds;
private boolean senderEnabled;
private int delay;
public void processInTurn()
{
}
public String getInboundQueue()
{
return this.inboundQueue;
}
public void setInboundQueue(String inboundQueue)
{
this.inboundQueue = inboundQueue;
}
public String getRouteName()
{
return this.routeName;
}
public void setRouteName(String routeName)
{
this.routeName = routeName;
}
public String getErrorQueue()
{
return this.errorQueue;
}
public void setErrorQueue(String errorQueue)
{
this.errorQueue = errorQueue;
}
public SequentialTransformer()
{
this.transformers = Collections.emptyList();
this.logger = LoggerFactory.getLogger(this.getClass());
this.setSenderEnabled(true);
}
public List<GenericTransformRoute> getTransformers()
{
return this.transformers;
}
@Autowired
public void setTransformers(List<GenericTransformRoute> transformers)
{
this.transformers = transformers;
}
public void setRedeliveryAttempts(int redeliveryAttempts)
{
this.redeliveryAttempts = redeliveryAttempts;
}
public int getRedeliveryAttempts()
{
return this.redeliveryAttempts;
}
public void setRedeliveryDelay(long redeliveryDelay)
{
this.redeliveryDelay = redeliveryDelay;
}
@Override
public void addRoutesToCamelContext(CamelContext context)
throws Exception
{
if (context instanceof DefaultCamelContext)
{
((DefaultCamelContext) context).setName(this.getRouteName());
}
String catcherName = String.format("direct:%s", this.getRouteName());
for (GenericTransformRoute transform : this.transformers)
{
String transformerInboundQueue =
String.format("direct:%s", transform.getRouteName());
// override source
transform.setInboundQueue(transformerInboundQueue);
transform.setOutboundQueue(catcherName);
transform.setRouteName(this.routeName + "-" + "%s" + "-" +
transform.getRouteName());
transform.setWorkerIds(this.getWorkerIds());
context.addRoutes(transform);
}
this.getSender().setInboundQueue(this.getSenderQueue());
this.getSender().setRouteName(this.routeName + "-sender");
this.getSender().setReceiverEndpoint(this.getReceiverEndpoint());
this.getSender().setErrorQueue(this.getErrorQueue());
this.getSender().setDelay(this.getDelay());
if (this.isSenderEnabled())
{
context.addRoutes(this.getSender());
}
super.addRoutesToCamelContext(context);
}
@Override
public void configure()
throws Exception
{
if (StringUtils.isEmpty(this.routeName)) { throw new IllegalArgumentException(
"routeName"); }
if (StringUtils.isEmpty(this.inboundQueue)) { throw new IllegalArgumentException(
"inboundQueue"); }
String catcherName = String.format("direct:%s", this.routeName);
if (this.getWorkerIds() == null)
this.logger
.info(String.format("Creating route %s", this.routeName));
this.defineExceptionHandlers();
if (this.getWorkerIds() != null)
for (String workerId : this.getWorkerIds())
{
this.logger.info(String.format(
"Creating route %s %s",
this.getInboundQueue(),
workerId));
ProcessorDefinition<RouteDefinition> policyDefinition =
this
.fromF(this.getInboundQueue(), workerId)
.routeId(this.routeName + "-" + workerId + "-start")
.unmarshal()
.custom("hl7dataformat")
/* .transacted("PROPAGATION_REQUIRED") */;
MulticastDefinition multicast = policyDefinition.multicast();
for (GenericTransformRoute transform : this.transformers)
{
multicast
.to(transform.getInboundQueue() + "-" + workerId)
.id(transform.getRouteName() + "-" + workerId);
}
this
.from(catcherName + "-" + workerId)
.routeId(this.routeName + "-" + workerId + "-end")
.log(
String.format(
"Processing MsgId: ${header.%s} / ${id}",
HL7Constants.HL7_MESSAGE_CONTROL))
// send to sender as flat string and not marshaled java
// object
.convertBodyTo(String.class)
.to(this.getSender().getInboundQueue());
}
}
protected void defineExceptionHandlers()
{
OnExceptionDefinition exceptionDefinition =
this.onException(Exception.class);
if (this.redeliveryAttempts != 0)
{
exceptionDefinition.maximumRedeliveries(this.redeliveryAttempts);
}
else
exceptionDefinition.maximumRedeliveries(-1);
if (this.redeliveryDelay != 0L)
{
exceptionDefinition.redeliveryDelay(this.redeliveryDelay);
}
else
exceptionDefinition.redeliveryDelay(1000L);
exceptionDefinition
.retryAttemptedLogLevel(LoggingLevel.ERROR)
.logRetryStackTrace(true)
.logRetryAttempted(true)
.maximumRedeliveryDelay(60000)
.backOffMultiplier(2)
.to(AbstractRouteBuilder.ERROR_LOG)
.to(this.errorQueue);
}
public GenericSender getSender()
{
return this.sender;
}
@Autowired
public void setSender(GenericSender sender)
{
this.sender = sender;
}
public String getSenderQueue()
{
return this.senderQueue;
}
public void setSenderQueue(String senderQueue)
{
this.senderQueue = senderQueue;
}
public String getReceiverEndpoint()
{
return this.receiverEndpoint;
}
public void setReceiverEndpoint(String receiverEndpoint)
{
this.receiverEndpoint = receiverEndpoint;
}
public String[] getWorkerIds()
{
return this.workerIds;
}
public void setWorkerIds(String[] workerIds)
{
this.workerIds = workerIds;
}
public boolean isSenderEnabled()
{
return this.senderEnabled;
}
public void setSenderEnabled(boolean senderEnabled)
{
this.senderEnabled = senderEnabled;
}
public int getDelay()
{
return this.delay;
}
public void setDelay(int delay)
{
this.delay = delay;
}
}