View Javadoc

1   /*
2    * $Id: AbstractMessageSequenceSplitter.java 22751 2011-08-26 00:42:38Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.routing.outbound;
12  
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  import org.mule.DefaultMuleEvent;
17  import org.mule.DefaultMuleMessage;
18  import org.mule.api.MuleContext;
19  import org.mule.api.MuleEvent;
20  import org.mule.api.MuleException;
21  import org.mule.api.MuleMessage;
22  import org.mule.api.context.MuleContextAware;
23  import org.mule.api.routing.MessageInfoMapping;
24  import org.mule.api.routing.RouterResultsHandler;
25  import org.mule.processor.AbstractInterceptingMessageProcessor;
26  import org.mule.routing.AbstractSplitter;
27  import org.mule.routing.CorrelationMode;
28  import org.mule.routing.DefaultRouterResultsHandler;
29  import org.mule.routing.MessageSequence;
30  
31  /**
32   * Base implementation of a {@link MuleMessage} splitter, that converts its payload 
33   * in a {@link MessageSequence}, and process each element of it.     
34   * Implementations must implement {@link #splitMessageIntoSequence(MuleEvent)} and determine how 
35   * the message is split.
36   * <p>
37   * <b>EIP Reference:</b> <a
38   * href="http://www.eaipatterns.com/Sequencer.html">http://www
39   * .eaipatterns.com/Sequencer.html</a>
40   * 
41   * @author flbulgarelli
42   * @see AbstractSplitter
43   */
44  public abstract class AbstractMessageSequenceSplitter extends AbstractInterceptingMessageProcessor
45      implements MuleContextAware
46  {
47      protected MuleContext muleContext;
48      protected RouterResultsHandler resultsHandler = new DefaultRouterResultsHandler();
49      protected CorrelationMode enableCorrelation = CorrelationMode.IF_NOT_SET;
50      protected MessageInfoMapping messageInfoMapping;
51  
52      public final MuleEvent process(MuleEvent event) throws MuleException
53      {
54          if (isSplitRequired(event))
55          {
56              MessageSequence<?> seq = splitMessageIntoSequence(event);
57              if (!seq.isEmpty())
58              {
59                  return resultsHandler.aggregateResults(processParts(seq, event), event, muleContext);
60              }
61              else
62              {
63                  logger.warn("Splitter returned no results. If this is not expected, please check your split expression");
64                  return null;
65              }
66          }
67          else
68          {
69              return processNext(event);
70          }
71      }
72  
73      protected boolean isSplitRequired(MuleEvent event)
74      {
75          return true;
76      }
77  
78      /**
79       * Converts the event into a {@link MessageSequence} that will retrieve each of
80       * the event elements
81       * 
82       * @param event the event to split
83       * @return a sequence of elements
84       * @throws MuleException
85       */
86      protected abstract MessageSequence<?> splitMessageIntoSequence(MuleEvent event) throws MuleException;
87  
88      protected List<MuleEvent> processParts(MessageSequence<?> seq, MuleEvent event) throws MuleException
89      {
90          if (messageInfoMapping == null)
91          {
92              messageInfoMapping = event.getFlowConstruct().getMessageInfoMapping();
93          }
94          String correlationId = messageInfoMapping.getCorrelationId(event.getMessage());
95          List<MuleEvent> resultEvents = new ArrayList<MuleEvent>();
96          int correlationSequence = 0;
97          int count = seq.size();
98          for (; seq.hasNext();)
99          {
100             Object payload = seq.next();
101             MuleMessage message = createMessage(payload, event.getMessage());
102             correlationSequence++;
103 
104             if (enableCorrelation != CorrelationMode.NEVER)
105             {
106                 boolean correlationSet = message.getCorrelationId() != null;
107                 if ((!correlationSet && (enableCorrelation == CorrelationMode.IF_NOT_SET))
108                     || (enableCorrelation == CorrelationMode.ALWAYS))
109                 {
110                     message.setCorrelationId(correlationId);
111                 }
112 
113                 // take correlation group size from the message properties, set by
114                 // concrete
115                 // message splitter implementations
116                 message.setCorrelationGroupSize(count);
117                 message.setCorrelationSequence(correlationSequence);
118             }
119             message.propagateRootId(event.getMessage());
120             resultEvents.add(processNext(new DefaultMuleEvent(message, event)));
121         }
122         if (correlationSequence == 1)
123         {
124             logger.warn("Splitter only returned a single result. If this is not expected, please check your split expression");
125         }
126         return resultEvents;
127     }
128 
129     private MuleMessage createMessage(Object payload, MuleMessage originalMessage)
130     {
131         if (payload instanceof MuleMessage)
132         {
133             return (MuleMessage) payload;
134         }
135         MuleMessage message = new DefaultMuleMessage(originalMessage, muleContext);
136         message.setPayload(payload);
137         return message;
138     }
139 
140     public void setEnableCorrelation(CorrelationMode enableCorrelation)
141     {
142         this.enableCorrelation = enableCorrelation;
143     }
144 
145     @Override
146     public void setMuleContext(MuleContext context)
147     {
148         this.muleContext = context;
149     }
150 
151     public void setMessageInfoMapping(MessageInfoMapping messageInfoMapping)
152     {
153         this.messageInfoMapping = messageInfoMapping;
154     }
155 }