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.function.Supplier;
021
022import org.apache.camel.spi.HeadersMapFactory;
023
024/**
025 * Implements the <a
026 * href="http://camel.apache.org/message.html">Message</a> pattern and
027 * represents an inbound or outbound message as part of an {@link Exchange}.
028 * <p/>
029 * Headers is represented in Camel using a {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
030 * The implementation of the map can be configured by the {@link HeadersMapFactory} which can be set
031 * on the {@link CamelContext}. The default implementation uses the {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
032 */
033public interface Message {
034
035    /**
036     * Returns the id of the message
037     *
038     * @return the message id
039     */
040    String getMessageId();
041
042    /**
043     * Sets the id of the message
044     *
045     * @param messageId id of the message
046     */
047    void setMessageId(String messageId);
048
049    /**
050     * Returns the exchange this message is related to
051     *
052     * @return the exchange
053     */
054    Exchange getExchange();
055
056    /**
057     * Accesses a specific header
058     *
059     * @param name  name of header
060     * @return the value of the given header or <tt>null</tt> if there is no
061     *         header for the given name
062     */
063    Object getHeader(String name);
064
065    /**
066     * Accesses a specific header
067     *
068     * @param name  name of header
069     * @param defaultValue the default value to return if header was absent
070     * @return the value of the given header or <tt>defaultValue</tt> if there is no
071     *         header for the given name
072     */
073    Object getHeader(String name, Object defaultValue);
074
075    /**
076     * Accesses a specific header
077     *
078     * @param name  name of header
079     * @param defaultValueSupplier the default value supplier used to generate the value to return if header was absent
080     * @return the value of the given header or he value generated by the <tt>defaultValueSupplier</tt> if there is no
081     *         header for the given name
082     */
083    Object getHeader(String name, Supplier<Object> defaultValueSupplier);
084
085    /**
086     * Returns a header associated with this message by name and specifying the
087     * type required
088     *
089     * @param name the name of the header
090     * @param type the type of the header
091     * @return the value of the given header or <tt>null</tt> if there is no header for
092     *         the given name
093     * @throws TypeConversionException is thrown if error during type conversion
094     */
095    <T> T getHeader(String name, Class<T> type);
096
097    /**
098     * Returns a header associated with this message by name and specifying the
099     * type required
100     *
101     * @param name the name of the header
102     * @param defaultValue the default value to return if header was absent
103     * @param type the type of the header
104     * @return the value of the given header or <tt>defaultValue</tt> if there is no header for
105     *         the given name or <tt>null</tt> if it cannot be converted to the given type
106     */
107    <T> T getHeader(String name, Object defaultValue, Class<T> type);
108
109    /**
110     * Returns a header associated with this message by name and specifying the
111     * type required
112     *
113     * @param name the name of the header
114     * @param defaultValueSupplier the default value supplier used to generate the value to return if header was absent
115     * @param type the type of the header
116     * @return the value of the given header or he value generated by the <tt>defaultValueSupplier</tt> if there is no
117     *         header for the given name or <tt>null</tt> if it cannot be converted to the given type
118     */
119    <T> T getHeader(String name, Supplier<Object> defaultValueSupplier, Class<T> type);
120
121    /**
122     * Sets a header on the message
123     *
124     * @param name of the header
125     * @param value to associate with the name
126     */
127    void setHeader(String name, Object value);
128
129    /**
130     * Removes the named header from this message
131     *
132     * @param name name of the header
133     * @return the old value of the header
134     */
135    Object removeHeader(String name);
136
137    /**
138     * Removes the headers from this message
139     *
140     * @param pattern pattern of names
141     * @return boolean whether any headers matched
142     */
143    boolean removeHeaders(String pattern);
144    
145    /**
146     * Removes the headers from this message that match the given <tt>pattern</tt>, 
147     * except for the ones matching one or more <tt>excludePatterns</tt>
148     * 
149     * @param pattern pattern of names that should be removed
150     * @param excludePatterns one or more pattern of header names that should be excluded (= preserved)
151     * @return boolean whether any headers matched
152     */ 
153    boolean removeHeaders(String pattern, String... excludePatterns);
154
155    /**
156     * Returns all of the headers associated with the message.
157     * <p/>
158     * Headers is represented in Camel using a {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
159     * The implementation of the map can be configured by the {@link HeadersMapFactory} which can be set
160     * on the {@link CamelContext}. The default implementation uses the {@link org.apache.camel.util.CaseInsensitiveMap CaseInsensitiveMap}.
161     * <p/>
162     * <b>Important:</b> If you want to walk the returned {@link Map} and fetch all the keys and values, you should use
163     * the {@link java.util.Map#entrySet()} method, which ensure you get the keys in the original case.
164     *
165     * @return all the headers in a Map
166     */
167    Map<String, Object> getHeaders();
168
169    /**
170     * Set all the headers associated with this message
171     * <p/>
172     * <b>Important:</b> If you want to copy headers from another {@link Message} to this {@link Message}, then
173     * use <tt>getHeaders().putAll(other)</tt> to copy the headers, where <tt>other</tt> is the other headers.
174     *
175     * @param headers headers to set
176     */
177    void setHeaders(Map<String, Object> headers);
178
179    /**
180     * Returns whether has any headers has been set.
181     *
182     * @return <tt>true</tt> if any headers has been set
183     */
184    boolean hasHeaders();
185
186    /**
187     * Returns the body of the message as a POJO
188     * <p/>
189     * The body can be <tt>null</tt> if no body is set.
190     * <p/>
191     * 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.
192     * 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).
193     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
194     *
195     * @return the body, can be <tt>null</tt>
196     */
197    Object getBody();
198
199    /**
200     * Returns the body of the message as a POJO
201     * <p/>
202     * 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.
203     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
204     *
205     * @return the body, is never <tt>null</tt>
206     * @throws InvalidPayloadException Is thrown if the body being <tt>null</tt> or wrong class type
207     */
208    Object getMandatoryBody() throws InvalidPayloadException;
209
210    /**
211     * Returns the body as the specified type
212     * <p/>
213     * 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.
214     * 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).
215     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
216     *
217     * @param type the type that the body
218     * @return the body of the message as the specified type, or <tt>null</tt> if no body exists
219     * @throws TypeConversionException is thrown if error during type conversion
220     */
221    <T> T getBody(Class<T> type);
222
223    /**
224     * Returns the mandatory body as the specified type
225     * <p/>
226     * 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.
227     * 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).
228     * See more details about <a href="http://camel.apache.org/stream-caching.html">stream caching</a>.
229     *
230     * @param type the type that the body
231     * @return the body of the message as the specified type, is never <tt>null</tt>.
232     * @throws InvalidPayloadException Is thrown if the body being <tt>null</tt> or wrong class type
233     */
234    <T> T getMandatoryBody(Class<T> type) throws InvalidPayloadException;
235
236    /**
237     * Sets the body of the message
238     *
239     * @param body the body
240     */
241    void setBody(Object body);
242
243    /**
244     * Sets the body of the message as a specific type
245     *
246     * @param body the body
247     * @param type the type of the body
248     */
249    <T> void setBody(Object body, Class<T> type);
250
251    /**
252     * Creates a copy of this message so that it can be used and possibly
253     * modified further in another exchange.
254     * <p/>
255     * The returned {@link Message} copy will have its {@link Exchange} set
256     * to the same {@link Exchange} instance as from the source.
257     *
258     * @return a new message instance copied from this message
259     */
260    Message copy();
261
262    /**
263     * Copies the contents of the other message into this message
264     * <p/>
265     * If you need to do a copy and then set a new body,
266     * then use {@link #copyFromWithNewBody(Message, Object)} method instead.
267     * <p/>
268     * The returned {@link Message} copy will have its {@link Exchange} set
269     * to the same {@link Exchange} instance as from the source.
270     *
271     * @param message the other message
272     * @see #copyFromWithNewBody(Message, Object)
273     */
274    void copyFrom(Message message);
275    
276    /**
277     * Copies the contents (except the body) of the other message into this message and uses the provided new body instead
278     * <p/>
279     * The returned {@link Message} copy will have its {@link Exchange} set
280     * to the same {@link Exchange} instance as from the source.
281     *
282     * @param message the other message
283     * @param newBody the new body to use
284     */
285    void copyFromWithNewBody(Message message, Object newBody);
286
287}