/* * Copyright 2014-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.support; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHeaders; import org.springframework.util.Assert; /** * @author Gary Russell * @since 4.0 * */ public abstract class AbstractIntegrationMessageBuilder<T> { public abstract T getPayload(); public abstract Map<String, Object> getHeaders(); /** * Set the value for the given header name. If the provided value is <code>null</code>, the header will be removed. * * @param headerName The header name. * @param headerValue The header value. * @return this. */ public abstract AbstractIntegrationMessageBuilder<T> setHeader(String headerName, Object headerValue); /** * Set the value for the given header name only if the header name is not already associated with a value. * * @param headerName The header name. * @param headerValue The header value. * @return this. */ public abstract AbstractIntegrationMessageBuilder<T> setHeaderIfAbsent(String headerName, Object headerValue); /** * Removes all headers provided via array of 'headerPatterns'. As the name suggests the array * may contain simple matching patterns for header names. Supported pattern styles are: * "xxx*", "*xxx", "*xxx*" and "xxx*yyy". * * @param headerPatterns The header patterns. * @return this. */ public abstract AbstractIntegrationMessageBuilder<T> removeHeaders(String... headerPatterns); /** * Remove the value for the given header name. * @param headerName The header name. * @return this. */ public abstract AbstractIntegrationMessageBuilder<T> removeHeader(String headerName); /** * Copy the name-value pairs from the provided Map. This operation will overwrite any existing values. Use { * {@link #copyHeadersIfAbsent(Map)} to avoid overwriting values. Note that the 'id' and 'timestamp' header values * will never be overwritten. * * @param headersToCopy The headers to copy. * @return this. * * @see MessageHeaders#ID * @see MessageHeaders#TIMESTAMP */ public abstract AbstractIntegrationMessageBuilder<T> copyHeaders(Map<String, ?> headersToCopy); /** * Copy the name-value pairs from the provided Map. This operation will <em>not</em> overwrite any existing values. * * @param headersToCopy The headers to copy. * @return this. */ public abstract AbstractIntegrationMessageBuilder<T> copyHeadersIfAbsent(Map<String, ?> headersToCopy); public AbstractIntegrationMessageBuilder<T> setExpirationDate(Long expirationDate) { return this.setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, expirationDate); } public AbstractIntegrationMessageBuilder<T> setExpirationDate(Date expirationDate) { if (expirationDate != null) { return this.setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, expirationDate.getTime()); } else { return this.setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, null); } } public AbstractIntegrationMessageBuilder<T> setCorrelationId(Object correlationId) { return this.setHeader(IntegrationMessageHeaderAccessor.CORRELATION_ID, correlationId); } public AbstractIntegrationMessageBuilder<T> pushSequenceDetails(Object correlationId, int sequenceNumber, int sequenceSize) { Object incomingCorrelationId = this.getCorrelationId(); List<List<Object>> incomingSequenceDetails = this.getSequenceDetails(); if (incomingCorrelationId != null) { if (incomingSequenceDetails == null) { incomingSequenceDetails = new ArrayList<List<Object>>(); } else { incomingSequenceDetails = new ArrayList<List<Object>>(incomingSequenceDetails); } incomingSequenceDetails.add(Arrays.asList(incomingCorrelationId, this.getSequenceNumber(), this.getSequenceSize())); incomingSequenceDetails = Collections.unmodifiableList(incomingSequenceDetails); } if (incomingSequenceDetails != null) { this.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS, incomingSequenceDetails); } return setCorrelationId(correlationId).setSequenceNumber(sequenceNumber).setSequenceSize(sequenceSize); } public AbstractIntegrationMessageBuilder<T> popSequenceDetails() { List<List<Object>> incomingSequenceDetails = this.getSequenceDetails(); if (incomingSequenceDetails == null) { return this; } else { incomingSequenceDetails = new ArrayList<List<Object>>(incomingSequenceDetails); } List<Object> sequenceDetails = incomingSequenceDetails.remove(incomingSequenceDetails.size() - 1); Assert.state(sequenceDetails.size() == 3, "Wrong sequence details (not created by MessageBuilder?): " + sequenceDetails); setCorrelationId(sequenceDetails.get(0)); Integer sequenceNumber = (Integer) sequenceDetails.get(1); Integer sequenceSize = (Integer) sequenceDetails.get(2); if (sequenceNumber != null) { setSequenceNumber(sequenceNumber); } if (sequenceSize != null) { setSequenceSize(sequenceSize); } if (!incomingSequenceDetails.isEmpty()) { this.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS, incomingSequenceDetails); } else { this.removeHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS); } return this; } protected abstract List<List<Object>> getSequenceDetails(); protected abstract Object getCorrelationId(); protected abstract Object getSequenceNumber(); protected abstract Object getSequenceSize(); public AbstractIntegrationMessageBuilder<T> setReplyChannel(MessageChannel replyChannel) { return this.setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel); } public AbstractIntegrationMessageBuilder<T> setReplyChannelName(String replyChannelName) { return this.setHeader(MessageHeaders.REPLY_CHANNEL, replyChannelName); } public AbstractIntegrationMessageBuilder<T> setErrorChannel(MessageChannel errorChannel) { return this.setHeader(MessageHeaders.ERROR_CHANNEL, errorChannel); } public AbstractIntegrationMessageBuilder<T> setErrorChannelName(String errorChannelName) { return this.setHeader(MessageHeaders.ERROR_CHANNEL, errorChannelName); } public AbstractIntegrationMessageBuilder<T> setSequenceNumber(Integer sequenceNumber) { return this.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, sequenceNumber); } public AbstractIntegrationMessageBuilder<T> setSequenceSize(Integer sequenceSize) { return this.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, sequenceSize); } public AbstractIntegrationMessageBuilder<T> setPriority(Integer priority) { return this.setHeader(IntegrationMessageHeaderAccessor.PRIORITY, priority); } public abstract Message<T> build(); }