/*
* Copyright 2016-2017 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.file.dsl;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.function.Function;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageSourceSpec;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.file.DirectoryScanner;
import org.springframework.integration.file.FileLocker;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.config.FileListFilterFactoryBean;
import org.springframework.integration.file.filters.AcceptAllFileListFilter;
import org.springframework.integration.file.filters.AcceptOnceFileListFilter;
import org.springframework.integration.file.filters.ExpressionFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.filters.IgnoreHiddenFileListFilter;
import org.springframework.integration.file.filters.RegexPatternFileListFilter;
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
import org.springframework.integration.file.locking.NioFileLocker;
import org.springframework.util.Assert;
/**
* A {@link MessageSourceSpec} for a {@link FileReadingMessageSource}.
*
* @author Artem Bilan
*
* @since 5.0
*/
public class FileInboundChannelAdapterSpec
extends MessageSourceSpec<FileInboundChannelAdapterSpec, FileReadingMessageSource>
implements ComponentsRegistration {
private final FileListFilterFactoryBean fileListFilterFactoryBean = new FileListFilterFactoryBean();
private FileLocker locker;
private ExpressionFileListFilter<File> expressionFileListFilter;
FileInboundChannelAdapterSpec() {
this.target = new FileReadingMessageSource();
}
FileInboundChannelAdapterSpec(Comparator<File> receptionOrderComparator) {
this.target = new FileReadingMessageSource(receptionOrderComparator) {
@Override
protected void onInit() {
try {
setFilter(FileInboundChannelAdapterSpec.this.fileListFilterFactoryBean.getObject());
}
catch (Exception e) {
throw new BeanCreationException("The bean for the [" + this + "] can not be instantiated.", e);
}
super.onInit();
}
};
}
/**
* Specify the input directory.
* @param directory the directory.
* @return the spec.
* @see FileReadingMessageSource#setDirectory(File)
*/
FileInboundChannelAdapterSpec directory(File directory) {
this.target.setDirectory(directory);
return _this();
}
/**
* Specify a custom scanner.
* @param scanner the scanner.
* @return the spec.
* @see FileReadingMessageSource#setScanner(DirectoryScanner)
*/
public FileInboundChannelAdapterSpec scanner(DirectoryScanner scanner) {
this.target.setScanner(scanner);
return _this();
}
/**
* Specify whether to create the source directory automatically if it does
* not yet exist upon initialization. By default, this value is
* <em>true</em>. If set to <em>false</em> and the
* source directory does not exist, an Exception will be thrown upon
* initialization.
* @param autoCreateDirectory the autoCreateDirectory.
* @return the spec.
* @see FileReadingMessageSource#setAutoCreateDirectory(boolean)
*/
public FileInboundChannelAdapterSpec autoCreateDirectory(boolean autoCreateDirectory) {
this.target.setAutoCreateDirectory(autoCreateDirectory);
return _this();
}
/**
* Configure the filter.
* @param filter the filter.
* @return the spec.
* @see FileReadingMessageSource#setFilter(FileListFilter)
*/
public FileInboundChannelAdapterSpec filter(FileListFilter<File> filter) {
this.fileListFilterFactoryBean.setFilter(filter);
return _this();
}
/**
* Configure the {@link ExpressionFileListFilter}.
* @param expression the SpEL expression for files filtering.
* @return the spec.
* @see FileReadingMessageSource#setFilter(FileListFilter)
* @see ExpressionFileListFilter
*/
public FileInboundChannelAdapterSpec filterExpression(String expression) {
this.expressionFileListFilter = new ExpressionFileListFilter<>(expression);
return filter(this.expressionFileListFilter);
}
/**
* Configure the {@link ExpressionFileListFilter}.
* @param filterFunction the {@link Function} for files filtering.
* @return the spec.
* @see FileReadingMessageSource#setFilter(FileListFilter)
* @see ExpressionFileListFilter
*/
public FileInboundChannelAdapterSpec filterFunction(Function<File, Boolean> filterFunction) {
this.expressionFileListFilter = new ExpressionFileListFilter<>(new FunctionExpression<>(filterFunction));
return filter(this.expressionFileListFilter);
}
/**
* Configure an {@link AcceptOnceFileListFilter} if {@code preventDuplicates == true},
* otherwise - {@link AcceptAllFileListFilter}.
* @param preventDuplicates true to configure an {@link AcceptOnceFileListFilter}.
* @return the spec.
*/
public FileInboundChannelAdapterSpec preventDuplicates(boolean preventDuplicates) {
this.fileListFilterFactoryBean.setPreventDuplicates(preventDuplicates);
return _this();
}
/**
/**
* Configure an {@link IgnoreHiddenFileListFilter} if {@code ignoreHidden == true}.
* @param ignoreHidden true to configure an {@link IgnoreHiddenFileListFilter}.
* @return the spec.
*/
public FileInboundChannelAdapterSpec ignoreHidden(boolean ignoreHidden) {
this.fileListFilterFactoryBean.setIgnoreHidden(ignoreHidden);
return _this();
}
/**
* Configure a {@link SimplePatternFileListFilter}.
* @param pattern The pattern.
* @return the spec.
* @see FileReadingMessageSource#setFilter(FileListFilter)
* @see #filter(FileListFilter)
*/
public FileInboundChannelAdapterSpec patternFilter(String pattern) {
this.fileListFilterFactoryBean.setFilenamePattern(pattern);
return _this();
}
/**
* Configure a {@link RegexPatternFileListFilter}.
* @param regex The regex.
* @return the spec.
* @see FileReadingMessageSource#setFilter(FileListFilter)
* @see #filter(FileListFilter)
*/
public FileInboundChannelAdapterSpec regexFilter(String regex) {
this.fileListFilterFactoryBean.setFilenameRegex(regex);
return _this();
}
/**
* Set a {@link FileLocker} to be used to guard files against
* duplicate processing.
* @param locker the locker.
* @return the spec.
* @see FileReadingMessageSource#setLocker(FileLocker)
*/
public FileInboundChannelAdapterSpec locker(FileLocker locker) {
Assert.isNull(this.locker,
"The 'locker' (" + this.locker + ") is already configured for the FileReadingMessageSource");
this.locker = locker;
this.target.setLocker(locker);
return _this();
}
/**
* Configure an {@link NioFileLocker}.
* @return the spec.
* @see #locker(FileLocker)
*/
public FileInboundChannelAdapterSpec nioLocker() {
return locker(new NioFileLocker());
}
/**
* Set this flag if you want to make sure the internal queue is
* refreshed with the latest content of the input directory on each poll.
* @param scanEachPoll the scanEachPoll.
* @return the spec.
* @see FileReadingMessageSource#setScanEachPoll(boolean)
*/
public FileInboundChannelAdapterSpec scanEachPoll(boolean scanEachPoll) {
this.target.setScanEachPoll(scanEachPoll);
return _this();
}
/**
* Switch this {@link FileReadingMessageSource} to use its internal
* {@link java.nio.file.WatchService} directory scanner.
* @param useWatchService the {@code boolean} flag to enable the use
* of a {@link java.nio.file.WatchService}.
* @return the spec.
* @see #watchEvents
* @see FileReadingMessageSource#setUseWatchService(boolean)
*/
public FileInboundChannelAdapterSpec useWatchService(boolean useWatchService) {
this.target.setUseWatchService(useWatchService);
return this;
}
/**
* The {@link java.nio.file.WatchService} event types.
* If {@link #useWatchService} isn't {@code true}, this option is ignored.
* @param watchEvents the set of {@link FileReadingMessageSource.WatchEventType}.
* @return the spec.
* @see #useWatchService
* @see FileReadingMessageSource#setWatchEvents
*/
public FileInboundChannelAdapterSpec watchEvents(FileReadingMessageSource.WatchEventType... watchEvents) {
this.target.setWatchEvents(watchEvents);
return this;
}
@Override
public Collection<Object> getComponentsToRegister() {
if (this.expressionFileListFilter != null) {
return Collections.singleton(this.expressionFileListFilter);
}
else {
return null;
}
}
}