/*
* Copyright 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.dsl;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.springframework.context.SmartLifecycle;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.dsl.channel.MessageChannelSpec;
import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.gateway.MessagingGatewaySupport;
import org.springframework.messaging.MessageChannel;
import org.springframework.util.Assert;
/**
* The base {@code Adapter} class for the {@link IntegrationFlow} abstraction.
* Requires the implementation for the {@link #buildFlow()} method to produce
* {@link IntegrationFlowDefinition} using one of {@link #from} support methods.
* <p>
* Typically is used for target service implementation:
* <pre class="code">
* @Component
* public class MyFlowAdapter extends IntegrationFlowAdapter {
*
* @Autowired
* private ConnectionFactory rabbitConnectionFactory;
*
* @Override
* protected IntegrationFlowDefinition<?> buildFlow() {
* return from(Amqp.inboundAdapter(this.rabbitConnectionFactory, "myQueue"))
* .<String, String>transform(String::toLowerCase)
* .channel(c -> c.queue("myFlowAdapterOutput"));
* }
*
* }
* </pre>
*
* @author Artem Bilan
*
* @since 5.0
*/
public abstract class IntegrationFlowAdapter implements IntegrationFlow, SmartLifecycle {
private final AtomicBoolean running = new AtomicBoolean();
private StandardIntegrationFlow targetIntegrationFlow;
@Override
public final void configure(IntegrationFlowDefinition<?> flow) {
IntegrationFlowDefinition<?> targetFlow = buildFlow();
Assert.state(targetFlow != null, "the 'buildFlow()' must not return null");
flow.integrationComponents.clear();
flow.integrationComponents.addAll(targetFlow.integrationComponents);
this.targetIntegrationFlow = flow.get();
}
@Override
public void start() {
assertTargetIntegrationFlow();
if (!this.running.getAndSet(true)) {
this.targetIntegrationFlow.start();
}
}
private void assertTargetIntegrationFlow() {
Assert.state(this.targetIntegrationFlow != null,
this + " hasn't been initialized properly via BeanFactory.\n"
+ "Missed @EnableIntegration ?");
}
@Override
public void stop(Runnable callback) {
assertTargetIntegrationFlow();
if (this.running.getAndSet(false)) {
this.targetIntegrationFlow.stop(callback);
}
}
@Override
public void stop() {
assertTargetIntegrationFlow();
if (this.running.getAndSet(false)) {
this.targetIntegrationFlow.stop();
}
}
@Override
public boolean isRunning() {
return this.running.get();
}
@Override
public boolean isAutoStartup() {
return false;
}
@Override
public int getPhase() {
return 0;
}
protected IntegrationFlowDefinition<?> from(String messageChannelName) {
return IntegrationFlows.from(messageChannelName);
}
protected IntegrationFlowDefinition<?> from(MessageChannel messageChannel) {
return IntegrationFlows.from(messageChannel);
}
protected IntegrationFlowDefinition<?> from(String messageChannelName, boolean fixedSubscriber) {
return IntegrationFlows.from(messageChannelName, fixedSubscriber);
}
protected IntegrationFlowDefinition<?> from(MessageSourceSpec<?, ? extends MessageSource<?>> messageSourceSpec,
Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
return IntegrationFlows.from(messageSourceSpec, endpointConfigurer);
}
protected IntegrationFlowDefinition<?> from(MessageSource<?> messageSource,
Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
return IntegrationFlows.from(messageSource, endpointConfigurer);
}
protected IntegrationFlowDefinition<?> from(MessageProducerSupport messageProducer) {
return IntegrationFlows.from(messageProducer);
}
protected IntegrationFlowDefinition<?> from(MessageSource<?> messageSource) {
return IntegrationFlows.from(messageSource);
}
protected IntegrationFlowDefinition<?> from(MessagingGatewaySupport inboundGateway) {
return IntegrationFlows.from(inboundGateway);
}
protected IntegrationFlowDefinition<?> from(MessageChannelSpec<?, ?> messageChannelSpec) {
return IntegrationFlows.from(messageChannelSpec);
}
protected IntegrationFlowDefinition<?> from(MessageProducerSpec<?, ?> messageProducerSpec) {
return IntegrationFlows.from(messageProducerSpec);
}
protected IntegrationFlowDefinition<?> from(MessageSourceSpec<?, ? extends MessageSource<?>> messageSourceSpec) {
return IntegrationFlows.from(messageSourceSpec);
}
protected IntegrationFlowDefinition<?> from(MessagingGatewaySpec<?, ?> inboundGatewaySpec) {
return IntegrationFlows.from(inboundGatewaySpec);
}
protected IntegrationFlowBuilder from(Object service, String methodName) {
return IntegrationFlows.from(service, methodName);
}
protected IntegrationFlowBuilder from(Object service, String methodName,
Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
return IntegrationFlows.from(service, methodName, endpointConfigurer);
}
protected abstract IntegrationFlowDefinition<?> buildFlow();
}