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