001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel;
018
019import java.util.Map;
020import java.util.Set;
021import java.util.function.Supplier;
022
023import javax.activation.DataHandler;
024
025import org.apache.camel.spi.HeadersMapFactory;
026
027/**
028 * Implements the <a
029 * href="http://camel.apache.org/message.html">Message</a> pattern and
030 * represents an inbound or outbound message as part of an {@link Exchange}.
031 * <p/>
032 * See {@link org.apache.camel.support.DefaultMessage DefaultMessage} for how headers
033 * is represented in Camel using a {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
034 * The implementation of the map can be configured by the {@link HeadersMapFactory} which can be set
035 * on the {@link CamelContext}. The default implementation uses the {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
036 */
037public interface Message {
038
039    /**
040     * Returns the id of the message
041     *
042     * @return the message id
043     */
044    String getMessageId();
045
046    /**
047     * Sets the id of the message
048     *
049     * @param messageId id of the message
050     */
051    void setMessageId(String messageId);
052
053    /**
054     * Returns the exchange this message is related to
055     *
056     * @return the exchange
057     */
058    Exchange getExchange();
059
060    /**
061     * Returns true if this message represents a fault
062     *
063     * @return <tt>true</tt> if this is a fault message, <tt>false</tt> for regular messages.
064     */
065    boolean isFault();
066
067    /**
068     * Sets the fault flag on this message
069     *
070     * @param fault the fault flag
071     */
072    void setFault(boolean fault);
073
074    /**
075     * Accesses a specific header
076     *
077     * @param name  name of header
078     * @return the value of the given header or <tt>null</tt> if there is no
079     *         header for the given name
080     */
081    Object getHeader(String name);
082
083    /**
084     * Accesses a specific header
085     *
086     * @param name  name of header
087     * @param defaultValue the default value to return if header was absent
088     * @return the value of the given header or <tt>defaultValue</tt> if there is no
089     *         header for the given name
090     */
091    Object getHeader(String name, Object defaultValue);
092
093    /**
094     * Accesses a specific header
095     *
096     * @param name  name of header
097     * @param defaultValueSupplier the default value supplier used to generate the value to return if header was absent
098     * @return the value of the given header or he value generated by the <tt>defaultValueSupplier</tt> if there is no
099     *         header for the given name
100     */
101    Object getHeader(String name, Supplier<Object> defaultValueSupplier);
102
103    /**
104     * Returns a header associated with this message by name and specifying the
105     * type required
106     *
107     * @param name the name of the header
108     * @param type the type of the header
109     * @return the value of the given header or <tt>null</tt> if there is no header for
110     *         the given name
111     * @throws TypeConversionException is thrown if error during type conversion
112     */
113    <T> T getHeader(String name, Class<T> type);
114
115    /**
116     * Returns a header associated with this message by name and specifying the
117     * type required
118     *
119     * @param name the name of the header
120     * @param defaultValue the default value to return if header was absent
121     * @param type the type of the header
122     * @return the value of the given header or <tt>defaultValue</tt> if there is no header for
123     *         the given name or <tt>null</tt> if it cannot be converted to the given type
124     */
125    <T> T getHeader(String name, Object defaultValue, Class<T> type);
126
127    /**
128     * Returns a header associated with this message by name and specifying the
129     * type required
130     *
131     * @param name the name of the header
132     * @param defaultValueSupplier the default value supplier used to generate the value to return if header was absent
133     * @param type the type of the header
134     * @return the value of the given header or he value generated by the <tt>defaultValueSupplier</tt> if there is no
135     *         header for the given name or <tt>null</tt> if it cannot be converted to the given type
136     */
137    <T> T getHeader(String name, Supplier<Object> defaultValueSupplier, Class<T> type);
138
139    /**
140     * Sets a header on the message
141     *
142     * @param name of the header
143     * @param value to associate with the name
144     */
145    void setHeader(String name, Object value);
146
147    /**
148     * Removes the named header from this message
149     *
150     * @param name name of the header
151     * @return the old value of the header
152     */
153    Object removeHeader(String name);
154
155    /**
156     * Removes the headers from this message
157     *
158     * @param pattern pattern of names
159     * @return boolean whether any headers matched
160     */
161    boolean removeHeaders(String pattern);
162    
163    /**
164     * Removes the headers from this message that match the given <tt>pattern</tt>, 
165     * except for the ones matching one or more <tt>excludePatterns</tt>
166     * 
167     * @param pattern pattern of names that should be removed
168     * @param excludePatterns one or more pattern of header names that should be excluded (= preserved)
169     * @return boolean whether any headers matched
170     */ 
171    boolean removeHeaders(String pattern, String... excludePatterns);
172
173    /**
174     * Returns all of the headers associated with the message.
175     * <p/>
176     * See {@link org.apache.camel.support.DefaultMessage DefaultMessage} for how headers
177     * is represented in Camel using a {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
178     * The implementation of the map can be configured by the {@link HeadersMapFactory} which can be set
179     * on the {@link CamelContext}. The default implementation uses the {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
180     * <p/>
181     * <b>Important:</b> If you want to walk the returned {@link Map} and fetch all the keys and values, you should use
182     * the {@link java.util.Map#entrySet()} method, which ensure you get the keys in the original case.
183     *
184     * @return all the headers in a Map
185     */
186    Map<String, Object> getHeaders();
187
188    /**
189     * Set all the headers associated with this message
190     * <p/>
191     * <b>Important:</b> If you want to copy headers from another {@link Message} to this {@link Message}, then
192     * use <tt>getHeaders().putAll(other)</tt> to copy the headers, where <tt>other</tt> is the other headers.
193     *
194     * @param headers headers to set
195     */
196    void setHeaders(Map<String, Object> headers);
197
198    /**
199     * Returns whether has any headers has been set.
200     *
201     * @return <tt>true</tt> if any headers has been set
202     */
203    boolean hasHeaders();
204
205    /**
206     * Returns the body of the message as a POJO
207     * <p/>
208     * The body can be <tt>null</tt> if no body is set.
209     * <p/>
210     * Notice if the message body is stream based then calling this method multiple times may lead to the stream not being able to be re-read again.
211     * You can enable stream caching and call the {@link StreamCache#reset()} method to reset the stream to be able to re-read again (if possible).
212     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
213     *
214     * @return the body, can be <tt>null</tt>
215     */
216    Object getBody();
217
218    /**
219     * Returns the body of the message as a POJO
220     * <p/>
221     * Notice if the message body is stream based then calling this method multiple times may lead to the stream not being able to be re-read again.
222     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
223     *
224     * @return the body, is never <tt>null</tt>
225     * @throws InvalidPayloadException Is thrown if the body being <tt>null</tt> or wrong class type
226     */
227    Object getMandatoryBody() throws InvalidPayloadException;
228
229    /**
230     * Returns the body as the specified type
231     * <p/>
232     * Notice if the message body is stream based then calling this method multiple times may lead to the stream not being able to be re-read again.
233     * You can enable stream caching and call the {@link StreamCache#reset()} method to reset the stream to be able to re-read again (if possible).
234     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
235     *
236     * @param type the type that the body
237     * @return the body of the message as the specified type, or <tt>null</tt> if no body exists
238     * @throws TypeConversionException is thrown if error during type conversion
239     */
240    <T> T getBody(Class<T> type);
241
242    /**
243     * Returns the mandatory body as the specified type
244     * <p/>
245     * Notice if the message body is stream based then calling this method multiple times may lead to the stream not being able to be re-read again.
246     * You can enable stream caching and call the {@link StreamCache#reset()} method to reset the stream to be able to re-read again (if possible).
247     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
248     *
249     * @param type the type that the body
250     * @return the body of the message as the specified type, is never <tt>null</tt>.
251     * @throws InvalidPayloadException Is thrown if the body being <tt>null</tt> or wrong class type
252     */
253    <T> T getMandatoryBody(Class<T> type) throws InvalidPayloadException;
254
255    /**
256     * Sets the body of the message
257     *
258     * @param body the body
259     */
260    void setBody(Object body);
261
262    /**
263     * Sets the body of the message as a specific type
264     *
265     * @param body the body
266     * @param type the type of the body
267     */
268    <T> void setBody(Object body, Class<T> type);
269
270    /**
271     * Creates a copy of this message so that it can be used and possibly
272     * modified further in another exchange.
273     * <p/>
274     * The returned {@link Message} copy will have its {@link Exchange} set
275     * to the same {@link Exchange} instance as from the source.
276     *
277     * @return a new message instance copied from this message
278     */
279    Message copy();
280
281    /**
282     * Copies the contents of the other message into this message
283     * <p/>
284     * If you need to do a copy and then set a new body,
285     * then use {@link #copyFromWithNewBody(Message, Object)} method instead.
286     * <p/>
287     * The returned {@link Message} copy will have its {@link Exchange} set
288     * to the same {@link Exchange} instance as from the source.
289     *
290     * @param message the other message
291     * @see #copyFromWithNewBody(Message, Object)
292     */
293    void copyFrom(Message message);
294    
295    /**
296     * Copies the contents (except the body) of the other message into this message and uses the provided new body instead
297     * <p/>
298     * The returned {@link Message} copy will have its {@link Exchange} set
299     * to the same {@link Exchange} instance as from the source.
300     *
301     * @param message the other message
302     * @param newBody the new body to use
303     */
304    void copyFromWithNewBody(Message message, Object newBody);
305
306    /**
307     * Copies the attachments of the other message into this message
308     *
309     * @param message the other message
310     */
311    void copyAttachments(Message message);
312
313    /**
314     * Returns the attachment specified by the id
315     *
316     * @param id the id under which the attachment is stored
317     * @return the data handler for this attachment or <tt>null</tt>
318     */
319    DataHandler getAttachment(String id);
320
321    /**
322     * Returns the attachment specified by the id
323     *
324     * @param id the id under which the attachment is stored
325     * @return the attachment or <tt>null</tt>
326     */
327    Attachment getAttachmentObject(String id);
328
329    /**
330     * Returns a set of attachment names of the message
331     *
332     * @return a set of attachment names
333     */
334    Set<String> getAttachmentNames();
335
336    /**
337     * Removes the attachment specified by the id
338     *
339     * @param id   the id of the attachment to remove
340     */
341    void removeAttachment(String id);
342
343    /**
344     * Adds an attachment to the message using the id
345     *
346     * @param id        the id to store the attachment under
347     * @param content   the data handler for the attachment
348     */
349    void addAttachment(String id, DataHandler content);
350
351    /**
352     * Adds an attachment to the message using the id
353     *
354     * @param id        the id to store the attachment under
355     * @param content   the attachment
356     */
357    void addAttachmentObject(String id, Attachment content);
358
359    /**
360     * Returns all attachments of the message
361     *
362     * @return the attachments in a map or <tt>null</tt>
363     */
364    Map<String, DataHandler> getAttachments();
365
366    /**
367     * Returns all attachments of the message
368     *
369     * @return the attachments in a map or <tt>null</tt>
370     */
371    Map<String, Attachment> getAttachmentObjects();
372
373    /**
374     * Set all the attachments associated with this message
375     *
376     * @param attachments the attachments
377     */
378    void setAttachments(Map<String, DataHandler> attachments);
379
380    /**
381     * Set all the attachments associated with this message
382     *
383     * @param attachments the attachments
384     */
385    void setAttachmentObjects(Map<String, Attachment> attachments);
386
387    /**
388     * Returns whether this message has attachments.
389     *
390     * @return <tt>true</tt> if this message has any attachments.
391     */
392    boolean hasAttachments();
393
394}