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.List; 020import java.util.Map; 021 022import org.apache.camel.spi.Synchronization; 023import org.apache.camel.spi.UnitOfWork; 024 025/** 026 * An Exchange is the message container holding the information during the entire routing of 027 * a {@link Message} received by a {@link Consumer}. 028 * <p/> 029 * During processing down the {@link Processor} chain, the {@link Exchange} provides access to the 030 * current (not the original) request and response {@link Message} messages. The {@link Exchange} 031 * also holds meta-data during its entire lifetime stored as properties accessible using the 032 * various {@link #getProperty(String)} methods. The {@link #setProperty(String, Object)} is 033 * used to store a property. For example you can use this to store security, SLA related 034 * data or any other information deemed useful throughout processing. If an {@link Exchange} 035 * failed during routing the {@link Exception} that caused the failure is stored and accessible 036 * via the {@link #getException()} method. 037 * <p/> 038 * An Exchange is created when a {@link Consumer} receives a request. A new {@link Message} is 039 * created, the request is set as the body of the {@link Message} and depending on the {@link Consumer} 040 * other {@link Endpoint} and protocol related information is added as headers on the {@link Message}. 041 * Then an Exchange is created and the newly created {@link Message} is set as the in on the Exchange. 042 * Therefore an Exchange starts its life in a {@link Consumer}. The Exchange is then sent down the 043 * {@link Route} for processing along a {@link Processor} chain. The {@link Processor} as the name 044 * suggests is what processes the {@link Message} in the Exchange and Camel, in addition to 045 * providing out-of-the-box a large number of useful processors, it also allows you to create your own. 046 * The rule Camel uses is to take the out {@link Message} produced by the previous {@link Processor} 047 * and set it as the in for the next {@link Processor}. If the previous {@link Processor} did not 048 * produce an out, then the in of the previous {@link Processor} is sent as the next in. At the 049 * end of the processing chain, depending on the {@link ExchangePattern Message Exchange Pattern} (or MEP) 050 * the last out (or in of no out available) is sent by the {@link Consumer} back to the original caller. 051 * <p/> 052 * Camel, in addition to providing out-of-the-box a large number of useful processors, it also allows 053 * you to implement and use your own. When the Exchange is passed to a {@link Processor}, it always 054 * contains an in {@link Message} and no out {@link Message}. The {@link Processor} <b>may</b> produce 055 * an out, depending on the nature of the {@link Processor}. The in {@link Message} can be accessed 056 * using the {@link #getIn()} method. Since the out message is null when entering the {@link Processor}, 057 * the {@link #getOut()} method is actually a convenient factory method that will lazily instantiate a 058 * {@link org.apache.camel.impl.DefaultMessage} which you could populate. As an alternative you could 059 * also instantiate your specialized {@link Message} and set it on the exchange using the 060 * {@link #setOut(org.apache.camel.Message)} method. Please note that a {@link Message} contains not only 061 * the body but also headers and attachments. If you are creating a new {@link Message} the headers and 062 * attachments of the in {@link Message} are not automatically copied to the out by Camel and you'll have 063 * to set the headers and attachments you need yourself. If your {@link Processor} is not producing a 064 * different {@link Message} but only needs to slightly modify the in, you can simply update the in 065 * {@link Message} returned by {@link #getIn()}. 066 * <p/> 067 * See this <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a> 068 * for more details. 069 * 070 */ 071public interface Exchange { 072 073 String AUTHENTICATION = "CamelAuthentication"; 074 String AUTHENTICATION_FAILURE_POLICY_ID = "CamelAuthenticationFailurePolicyId"; 075 String ACCEPT_CONTENT_TYPE = "CamelAcceptContentType"; 076 String AGGREGATED_SIZE = "CamelAggregatedSize"; 077 String AGGREGATED_TIMEOUT = "CamelAggregatedTimeout"; 078 String AGGREGATED_COMPLETED_BY = "CamelAggregatedCompletedBy"; 079 String AGGREGATED_CORRELATION_KEY = "CamelAggregatedCorrelationKey"; 080 String AGGREGATION_STRATEGY = "CamelAggregationStrategy"; 081 String AGGREGATION_COMPLETE_CURRENT_GROUP = "CamelAggregationCompleteCurrentGroup"; 082 String AGGREGATION_COMPLETE_ALL_GROUPS = "CamelAggregationCompleteAllGroups"; 083 String AGGREGATION_COMPLETE_ALL_GROUPS_INCLUSIVE = "CamelAggregationCompleteAllGroupsInclusive"; 084 String ASYNC_WAIT = "CamelAsyncWait"; 085 086 String BATCH_INDEX = "CamelBatchIndex"; 087 String BATCH_SIZE = "CamelBatchSize"; 088 String BATCH_COMPLETE = "CamelBatchComplete"; 089 String BEAN_METHOD_NAME = "CamelBeanMethodName"; 090 String BEAN_MULTI_PARAMETER_ARRAY = "CamelBeanMultiParameterArray"; 091 String BINDING = "CamelBinding"; 092 // do not prefix with Camel and use lower-case starting letter as its a shared key 093 // used across other Apache products such as AMQ, SMX etc. 094 String BREADCRUMB_ID = "breadcrumbId"; 095 096 String CHARSET_NAME = "CamelCharsetName"; 097 String CREATED_TIMESTAMP = "CamelCreatedTimestamp"; 098 String CONTENT_ENCODING = "Content-Encoding"; 099 String CONTENT_LENGTH = "Content-Length"; 100 String CONTENT_TYPE = "Content-Type"; 101 String CORRELATION_ID = "CamelCorrelationId"; 102 103 String DATASET_INDEX = "CamelDataSetIndex"; 104 String DEFAULT_CHARSET_PROPERTY = "org.apache.camel.default.charset"; 105 String DESTINATION_OVERRIDE_URL = "CamelDestinationOverrideUrl"; 106 String DISABLE_HTTP_STREAM_CACHE = "CamelDisableHttpStreamCache"; 107 String DUPLICATE_MESSAGE = "CamelDuplicateMessage"; 108 109 String DOCUMENT_BUILDER_FACTORY = "CamelDocumentBuilderFactory"; 110 111 String EXCEPTION_CAUGHT = "CamelExceptionCaught"; 112 String EXCEPTION_HANDLED = "CamelExceptionHandled"; 113 String EVALUATE_EXPRESSION_RESULT = "CamelEvaluateExpressionResult"; 114 String ERRORHANDLER_HANDLED = "CamelErrorHandlerHandled"; 115 String EXTERNAL_REDELIVERED = "CamelExternalRedelivered"; 116 117 String FAILURE_HANDLED = "CamelFailureHandled"; 118 String FAILURE_ENDPOINT = "CamelFailureEndpoint"; 119 String FAILURE_ROUTE_ID = "CamelFailureRouteId"; 120 String FILTER_NON_XML_CHARS = "CamelFilterNonXmlChars"; 121 String FILE_CONTENT_TYPE = "CamelFileContentType"; 122 String FILE_LOCAL_WORK_PATH = "CamelFileLocalWorkPath"; 123 String FILE_NAME = "CamelFileName"; 124 String FILE_NAME_ONLY = "CamelFileNameOnly"; 125 String FILE_NAME_PRODUCED = "CamelFileNameProduced"; 126 String FILE_NAME_CONSUMED = "CamelFileNameConsumed"; 127 String FILE_PATH = "CamelFilePath"; 128 String FILE_PARENT = "CamelFileParent"; 129 String FILE_LAST_MODIFIED = "CamelFileLastModified"; 130 String FILE_LENGTH = "CamelFileLength"; 131 String FILTER_MATCHED = "CamelFilterMatched"; 132 String FILE_LOCK_FILE_ACQUIRED = "CamelFileLockFileAcquired"; 133 String FILE_LOCK_FILE_NAME = "CamelFileLockFileName"; 134 String FILE_LOCK_EXCLUSIVE_LOCK = "CamelFileLockExclusiveLock"; 135 String FILE_LOCK_RANDOM_ACCESS_FILE = "CamelFileLockRandomAccessFile"; 136 137 String GROUPED_EXCHANGE = "CamelGroupedExchange"; 138 139 String HTTP_BASE_URI = "CamelHttpBaseUri"; 140 String HTTP_CHARACTER_ENCODING = "CamelHttpCharacterEncoding"; 141 String HTTP_METHOD = "CamelHttpMethod"; 142 String HTTP_PATH = "CamelHttpPath"; 143 String HTTP_PROTOCOL_VERSION = "CamelHttpProtocolVersion"; 144 String HTTP_QUERY = "CamelHttpQuery"; 145 String HTTP_RAW_QUERY = "CamelHttpRawQuery"; 146 String HTTP_RESPONSE_CODE = "CamelHttpResponseCode"; 147 String HTTP_URI = "CamelHttpUri"; 148 String HTTP_URL = "CamelHttpUrl"; 149 String HTTP_CHUNKED = "CamelHttpChunked"; 150 String HTTP_SERVLET_REQUEST = "CamelHttpServletRequest"; 151 String HTTP_SERVLET_RESPONSE = "CamelHttpServletResponse"; 152 153 String INTERCEPTED_ENDPOINT = "CamelInterceptedEndpoint"; 154 String INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED = "CamelInterceptSendToEndpointWhenMatched"; 155 156 String LANGUAGE_SCRIPT = "CamelLanguageScript"; 157 String LOG_DEBUG_BODY_MAX_CHARS = "CamelLogDebugBodyMaxChars"; 158 String LOG_DEBUG_BODY_STREAMS = "CamelLogDebugStreams"; 159 String LOOP_INDEX = "CamelLoopIndex"; 160 String LOOP_SIZE = "CamelLoopSize"; 161 162 String MAXIMUM_CACHE_POOL_SIZE = "CamelMaximumCachePoolSize"; 163 String MAXIMUM_ENDPOINT_CACHE_SIZE = "CamelMaximumEndpointCacheSize"; 164 String MESSAGE_HISTORY = "CamelMessageHistory"; 165 String MULTICAST_INDEX = "CamelMulticastIndex"; 166 String MULTICAST_COMPLETE = "CamelMulticastComplete"; 167 168 String NOTIFY_EVENT = "CamelNotifyEvent"; 169 170 String ON_COMPLETION = "CamelOnCompletion"; 171 String OVERRULE_FILE_NAME = "CamelOverruleFileName"; 172 173 String PARENT_UNIT_OF_WORK = "CamelParentUnitOfWork"; 174 String STREAM_CACHE_UNIT_OF_WORK = "CamelStreamCacheUnitOfWork"; 175 176 String RECIPIENT_LIST_ENDPOINT = "CamelRecipientListEndpoint"; 177 String RECEIVED_TIMESTAMP = "CamelReceivedTimestamp"; 178 String REDELIVERED = "CamelRedelivered"; 179 String REDELIVERY_COUNTER = "CamelRedeliveryCounter"; 180 String REDELIVERY_MAX_COUNTER = "CamelRedeliveryMaxCounter"; 181 String REDELIVERY_EXHAUSTED = "CamelRedeliveryExhausted"; 182 String REDELIVERY_DELAY = "CamelRedeliveryDelay"; 183 String ROLLBACK_ONLY = "CamelRollbackOnly"; 184 String ROLLBACK_ONLY_LAST = "CamelRollbackOnlyLast"; 185 String ROUTE_STOP = "CamelRouteStop"; 186 187 String REUSE_SCRIPT_ENGINE = "CamelReuseScripteEngine"; 188 String COMPILE_SCRIPT = "CamelCompileScript"; 189 190 String SAXPARSER_FACTORY = "CamelSAXParserFactory"; 191 192 String SCHEDULER_POLLED_MESSAGES = "CamelSchedulerPolledMessages"; 193 String SOAP_ACTION = "CamelSoapAction"; 194 String SKIP_GZIP_ENCODING = "CamelSkipGzipEncoding"; 195 String SKIP_WWW_FORM_URLENCODED = "CamelSkipWwwFormUrlEncoding"; 196 String SLIP_ENDPOINT = "CamelSlipEndpoint"; 197 String SPLIT_INDEX = "CamelSplitIndex"; 198 String SPLIT_COMPLETE = "CamelSplitComplete"; 199 String SPLIT_SIZE = "CamelSplitSize"; 200 201 String TIMER_COUNTER = "CamelTimerCounter"; 202 String TIMER_FIRED_TIME = "CamelTimerFiredTime"; 203 String TIMER_NAME = "CamelTimerName"; 204 String TIMER_PERIOD = "CamelTimerPeriod"; 205 String TIMER_TIME = "CamelTimerTime"; 206 String TO_ENDPOINT = "CamelToEndpoint"; 207 String TRACE_EVENT = "CamelTraceEvent"; 208 String TRACE_EVENT_NODE_ID = "CamelTraceEventNodeId"; 209 String TRACE_EVENT_TIMESTAMP = "CamelTraceEventTimestamp"; 210 String TRACE_EVENT_EXCHANGE = "CamelTraceEventExchange"; 211 String TRY_ROUTE_BLOCK = "TryRouteBlock"; 212 String TRANSFER_ENCODING = "Transfer-Encoding"; 213 214 String UNIT_OF_WORK_EXHAUSTED = "CamelUnitOfWorkExhausted"; 215 216 /** 217 * @deprecated UNIT_OF_WORK_PROCESS_SYNC is not in use and will be removed in future Camel release 218 */ 219 @Deprecated 220 String UNIT_OF_WORK_PROCESS_SYNC = "CamelUnitOfWorkProcessSync"; 221 222 String XSLT_FILE_NAME = "CamelXsltFileName"; 223 String XSLT_ERROR = "CamelXsltError"; 224 String XSLT_FATAL_ERROR = "CamelXsltFatalError"; 225 String XSLT_WARNING = "CamelXsltWarning"; 226 227 /** 228 * Returns the {@link ExchangePattern} (MEP) of this exchange. 229 * 230 * @return the message exchange pattern of this exchange 231 */ 232 ExchangePattern getPattern(); 233 234 /** 235 * Allows the {@link ExchangePattern} (MEP) of this exchange to be customized. 236 * 237 * This typically won't be required as an exchange can be created with a specific MEP 238 * by calling {@link Endpoint#createExchange(ExchangePattern)} but it is here just in case 239 * it is needed. 240 * 241 * @param pattern the pattern 242 */ 243 void setPattern(ExchangePattern pattern); 244 245 /** 246 * Returns a property associated with this exchange by name 247 * 248 * @param name the name of the property 249 * @return the value of the given property or <tt>null</tt> if there is no property for 250 * the given name 251 */ 252 Object getProperty(String name); 253 254 /** 255 * Returns a property associated with this exchange by name 256 * 257 * @param name the name of the property 258 * @param defaultValue the default value to return if property was absent 259 * @return the value of the given property or <tt>defaultValue</tt> if there is no 260 * property for the given name 261 */ 262 Object getProperty(String name, Object defaultValue); 263 264 /** 265 * Returns a property associated with this exchange by name and specifying 266 * the type required 267 * 268 * @param name the name of the property 269 * @param type the type of the property 270 * @return the value of the given property or <tt>null</tt> if there is no property for 271 * the given name or <tt>null</tt> if it cannot be converted to the given type 272 */ 273 <T> T getProperty(String name, Class<T> type); 274 275 /** 276 * Returns a property associated with this exchange by name and specifying 277 * the type required 278 * 279 * @param name the name of the property 280 * @param defaultValue the default value to return if property was absent 281 * @param type the type of the property 282 * @return the value of the given property or <tt>defaultValue</tt> if there is no property for 283 * the given name or <tt>null</tt> if it cannot be converted to the given type 284 */ 285 <T> T getProperty(String name, Object defaultValue, Class<T> type); 286 287 /** 288 * Sets a property on the exchange 289 * 290 * @param name of the property 291 * @param value to associate with the name 292 */ 293 void setProperty(String name, Object value); 294 295 /** 296 * Removes the given property on the exchange 297 * 298 * @param name of the property 299 * @return the old value of the property 300 */ 301 Object removeProperty(String name); 302 303 /** 304 * Remove all of the properties associated with the exchange matching a specific pattern 305 * 306 * @param pattern pattern of names 307 * @return boolean whether any properties matched 308 */ 309 boolean removeProperties(String pattern); 310 311 /** 312 * Removes the properties from this exchange that match the given <tt>pattern</tt>, 313 * except for the ones matching one ore more <tt>excludePatterns</tt> 314 * 315 * @param pattern pattern of names that should be removed 316 * @param excludePatterns one or more pattern of properties names that should be excluded (= preserved) 317 * @return boolean whether any properties matched 318 */ 319 boolean removeProperties(String pattern, String... excludePatterns); 320 321 /** 322 * Returns all of the properties associated with the exchange 323 * 324 * @return all the headers in a Map 325 */ 326 Map<String, Object> getProperties(); 327 328 /** 329 * Returns whether any properties has been set 330 * 331 * @return <tt>true</tt> if any properties has been set 332 */ 333 boolean hasProperties(); 334 335 /** 336 * Returns the inbound request message 337 * 338 * @return the message 339 */ 340 Message getIn(); 341 342 /** 343 * Returns the inbound request message as the given type 344 * 345 * @param type the given type 346 * @return the message as the given type or <tt>null</tt> if not possible to covert to given type 347 */ 348 <T> T getIn(Class<T> type); 349 350 /** 351 * Sets the inbound message instance 352 * 353 * @param in the inbound message 354 */ 355 void setIn(Message in); 356 357 /** 358 * Returns the outbound message, lazily creating one if one has not already 359 * been associated with this exchange. 360 * <p/> 361 * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will 362 * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use 363 * this method. 364 * <p/> 365 * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method. 366 * <p/> 367 * See also the class java doc for this {@link Exchange} for more details and this 368 * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>. 369 * 370 * @return the response 371 * @see #getIn() 372 */ 373 Message getOut(); 374 375 /** 376 * Returns the outbound request message as the given type 377 * <p/> 378 * <br/><b>Important:</b> If you want to change the current message, then use {@link #getIn()} instead as it will 379 * ensure headers etc. is kept and propagated when routing continues. Bottom line end users should rarely use 380 * this method. 381 * <p/> 382 * <br/>If you want to test whether an OUT message have been set or not, use the {@link #hasOut()} method. 383 * <p/> 384 * See also the class java doc for this {@link Exchange} for more details and this 385 * <a href="http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html">FAQ entry</a>. 386 * 387 * @param type the given type 388 * @return the message as the given type or <tt>null</tt> if not possible to covert to given type 389 * @see #getIn(Class) 390 */ 391 <T> T getOut(Class<T> type); 392 393 /** 394 * Returns whether an OUT message has been set or not. 395 * 396 * @return <tt>true</tt> if an OUT message exists, <tt>false</tt> otherwise. 397 */ 398 boolean hasOut(); 399 400 /** 401 * Sets the outbound message 402 * 403 * @param out the outbound message 404 */ 405 void setOut(Message out); 406 407 /** 408 * Returns the exception associated with this exchange 409 * 410 * @return the exception (or null if no faults) 411 */ 412 Exception getException(); 413 414 /** 415 * Returns the exception associated with this exchange. 416 * <p/> 417 * Is used to get the caused exception that typically have been wrapped in some sort 418 * of Camel wrapper exception 419 * <p/> 420 * The strategy is to look in the exception hierarchy to find the first given cause that matches the type. 421 * Will start from the bottom (the real cause) and walk upwards. 422 * 423 * @param type the exception type 424 * @return the exception (or <tt>null</tt> if no caused exception matched) 425 */ 426 <T> T getException(Class<T> type); 427 428 /** 429 * Sets the exception associated with this exchange 430 * <p/> 431 * Camel will wrap {@link Throwable} into {@link Exception} type to 432 * accommodate for the {@link #getException()} method returning a plain {@link Exception} type. 433 * 434 * @param t the caused exception 435 */ 436 void setException(Throwable t); 437 438 /** 439 * Returns true if this exchange failed due to either an exception or fault 440 * 441 * @return true if this exchange failed due to either an exception or fault 442 * @see Exchange#getException() 443 * @see Message#setFault(boolean) 444 * @see Message#isFault() 445 */ 446 boolean isFailed(); 447 448 /** 449 * Returns true if this exchange is transacted 450 */ 451 boolean isTransacted(); 452 453 /** 454 * Returns true if this exchange is an external initiated redelivered message (such as a JMS broker). 455 * <p/> 456 * <b>Important: </b> It is not always possible to determine if the message is a redelivery 457 * or not, and therefore <tt>null</tt> is returned. Such an example would be a JDBC message. 458 * However JMS brokers provides details if a message is redelivered. 459 * 460 * @return <tt>true</tt> if redelivered, <tt>false</tt> if not, <tt>null</tt> if not able to determine 461 */ 462 Boolean isExternalRedelivered(); 463 464 /** 465 * Returns true if this exchange is marked for rollback 466 */ 467 boolean isRollbackOnly(); 468 469 /** 470 * Returns the container so that a processor can resolve endpoints from URIs 471 * 472 * @return the container which owns this exchange 473 */ 474 CamelContext getContext(); 475 476 /** 477 * Creates a copy of the current message exchange so that it can be 478 * forwarded to another destination 479 */ 480 Exchange copy(); 481 482 /** 483 * Returns the endpoint which originated this message exchange if a consumer on an endpoint 484 * created the message exchange, otherwise this property will be <tt>null</tt> 485 */ 486 Endpoint getFromEndpoint(); 487 488 /** 489 * Sets the endpoint which originated this message exchange. This method 490 * should typically only be called by {@link org.apache.camel.Endpoint} implementations 491 * 492 * @param fromEndpoint the endpoint which is originating this message exchange 493 */ 494 void setFromEndpoint(Endpoint fromEndpoint); 495 496 /** 497 * Returns the route id which originated this message exchange if a route consumer on an endpoint 498 * created the message exchange, otherwise this property will be <tt>null</tt> 499 */ 500 String getFromRouteId(); 501 502 /** 503 * Sets the route id which originated this message exchange. This method 504 * should typically only be called by the internal framework. 505 * 506 * @param fromRouteId the from route id 507 */ 508 void setFromRouteId(String fromRouteId); 509 510 /** 511 * Returns the unit of work that this exchange belongs to; which may map to 512 * zero, one or more physical transactions 513 */ 514 UnitOfWork getUnitOfWork(); 515 516 /** 517 * Sets the unit of work that this exchange belongs to; which may map to 518 * zero, one or more physical transactions 519 */ 520 void setUnitOfWork(UnitOfWork unitOfWork); 521 522 /** 523 * Returns the exchange id (unique) 524 */ 525 String getExchangeId(); 526 527 /** 528 * Set the exchange id 529 */ 530 void setExchangeId(String id); 531 532 /** 533 * Adds a {@link org.apache.camel.spi.Synchronization} to be invoked as callback when 534 * this exchange is completed. 535 * 536 * @param onCompletion the callback to invoke on completion of this exchange 537 */ 538 void addOnCompletion(Synchronization onCompletion); 539 540 /** 541 * Checks if the passed {@link org.apache.camel.spi.Synchronization} instance is 542 * already contained on this exchange. 543 * 544 * @param onCompletion the callback instance that is being checked for 545 * @return <tt>true</tt>, if callback instance is already contained on this exchange, else <tt>false</tt> 546 */ 547 boolean containsOnCompletion(Synchronization onCompletion); 548 549 /** 550 * Handover all the on completions from this exchange to the target exchange. 551 * 552 * @param target the target exchange 553 */ 554 void handoverCompletions(Exchange target); 555 556 /** 557 * Handover all the on completions from this exchange 558 * 559 * @return the on completions 560 */ 561 List<Synchronization> handoverCompletions(); 562 563 564}