All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.integration.support.AbstractIntegrationMessageBuilder Maven / Gradle / Ivy

There is a newer version: 6.3.3
Show newest version
/*
 * Copyright 2014-2019 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
 *
 *      https://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.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PatternMatchUtils;

/**
 * @author Gary Russell
 * @author Artem Bilan
 *
 * @since 4.0
 *
 */
public abstract class AbstractIntegrationMessageBuilder {

	public AbstractIntegrationMessageBuilder setExpirationDate(Long expirationDate) {
		return setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, expirationDate);
	}

	public AbstractIntegrationMessageBuilder setExpirationDate(Date expirationDate) {
		if (expirationDate != null) {
			return setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, expirationDate.getTime());
		}
		else {
			return setHeader(IntegrationMessageHeaderAccessor.EXPIRATION_DATE, null);
		}
	}

	public AbstractIntegrationMessageBuilder setCorrelationId(Object correlationId) {
		return setHeader(IntegrationMessageHeaderAccessor.CORRELATION_ID, correlationId);
	}

	public AbstractIntegrationMessageBuilder pushSequenceDetails(Object correlationId, int sequenceNumber,
			int sequenceSize) {

		Object incomingCorrelationId = this.getCorrelationId();
		List> incomingSequenceDetails = getSequenceDetails();
		if (incomingCorrelationId != null) {
			if (incomingSequenceDetails == null) {
				incomingSequenceDetails = new ArrayList<>();
			}
			else {
				incomingSequenceDetails = new ArrayList<>(incomingSequenceDetails);
			}
			incomingSequenceDetails.add(Arrays.asList(incomingCorrelationId,
					getSequenceNumber(), getSequenceSize()));
			incomingSequenceDetails = Collections.unmodifiableList(incomingSequenceDetails);
		}
		if (incomingSequenceDetails != null) {
			setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS, incomingSequenceDetails);
		}
		return setCorrelationId(correlationId)
				.setSequenceNumber(sequenceNumber)
				.setSequenceSize(sequenceSize);
	}

	public AbstractIntegrationMessageBuilder popSequenceDetails() {
		List> incomingSequenceDetails = getSequenceDetails();
		if (incomingSequenceDetails == null) {
			return this;
		}
		else {
			incomingSequenceDetails = new ArrayList<>(incomingSequenceDetails);
		}
		List 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()) {
			setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS, incomingSequenceDetails);
		}
		else {
			removeHeader(IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS);
		}
		return this;
	}

	public AbstractIntegrationMessageBuilder setReplyChannel(MessageChannel replyChannel) {
		return setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel);
	}

	public AbstractIntegrationMessageBuilder setReplyChannelName(String replyChannelName) {
		return setHeader(MessageHeaders.REPLY_CHANNEL, replyChannelName);
	}

	public AbstractIntegrationMessageBuilder setErrorChannel(MessageChannel errorChannel) {
		return setHeader(MessageHeaders.ERROR_CHANNEL, errorChannel);
	}

	public AbstractIntegrationMessageBuilder setErrorChannelName(String errorChannelName) {
		return setHeader(MessageHeaders.ERROR_CHANNEL, errorChannelName);
	}

	public AbstractIntegrationMessageBuilder setSequenceNumber(Integer sequenceNumber) {
		return setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, sequenceNumber);
	}

	public AbstractIntegrationMessageBuilder setSequenceSize(Integer sequenceSize) {
		return setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, sequenceSize);
	}

	public AbstractIntegrationMessageBuilder setPriority(Integer priority) {
		return setHeader(IntegrationMessageHeaderAccessor.PRIORITY, priority);
	}

	/**
	 * Remove headers from the provided map matching to the provided pattens
	 * and only after that copy the result into the target message headers.
	 * @param headersToCopy a map of headers to copy.
	 * @param headerPatternsToFilter an arrays of header patterns to filter before copying.
	 * @return the current {@link AbstractIntegrationMessageBuilder}.
	 * @since 5.1
	 * @see #copyHeadersIfAbsent(Map)
	 */
	public AbstractIntegrationMessageBuilder filterAndCopyHeadersIfAbsent(Map headersToCopy,
			@Nullable String... headerPatternsToFilter) {

		Map headers = headersToCopy;

		if (!ObjectUtils.isEmpty(headerPatternsToFilter)) {
			headers = new HashMap<>(headersToCopy);
			headers.entrySet()
					.removeIf(entry -> PatternMatchUtils.simpleMatch(headerPatternsToFilter, entry.getKey()));
		}

		return copyHeadersIfAbsent(headers);
	}

	@Nullable
	protected abstract List> getSequenceDetails();

	protected abstract Object getCorrelationId();

	protected abstract Object getSequenceNumber();

	protected abstract Object getSequenceSize();

	public abstract T getPayload();

	public abstract Map getHeaders();

	@Nullable
	public abstract  V getHeader(String key, Class type);

	/**
	 * Set the value for the given header name. If the provided value is null, the header will be removed.
	 * @param headerName The header name.
	 * @param headerValue The header value.
	 * @return this.
	 */
	public abstract AbstractIntegrationMessageBuilder setHeader(String headerName, @Nullable 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 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 removeHeaders(String... headerPatterns);

	/**
	 * Remove the value for the given header name.
	 * @param headerName The header name.
	 * @return this.
	 */
	public abstract AbstractIntegrationMessageBuilder 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 copyHeaders(@Nullable Map headersToCopy);

	/**
	 * Copy the name-value pairs from the provided Map. This operation will not overwrite any existing values.
	 * @param headersToCopy The headers to copy.
	 * @return this.
	 */
	public abstract AbstractIntegrationMessageBuilder copyHeadersIfAbsent(@Nullable Map headersToCopy);

	public abstract Message build();

}