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