polishing

This commit is contained in:
Mark Fisher
2010-11-05 14:50:37 -04:00
parent 6abae5412b
commit 12d0d46fc4
9 changed files with 93 additions and 77 deletions

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
import org.springframework.beans.factory.InitializingBean;
@@ -20,7 +21,6 @@ import org.springframework.beans.factory.InitializingBean;
import java.util.ArrayList;
import java.util.List;
/**
* A convenience base class for any {@link EntryListFilter} whose criteria can be
* evaluated against each File in isolation. If the entire List of files is
@@ -31,14 +31,18 @@ import java.util.List;
* @author Josh Long
*/
public abstract class AbstractEntryListFilter<T> implements InitializingBean, EntryListFilter<T> {
public abstract boolean accept(T t);
/**
* subclasses may override this if initialization is required
*/
public void afterPropertiesSet() throws Exception {
}
/**
* {@inheritDoc}
*/
public List<T> filterEntries(T[] entries) {
List<T> accepted = new ArrayList<T>();
if (entries != null) {
for (T t : entries) {
if (this.accept(t)) {
@@ -46,11 +50,12 @@ public abstract class AbstractEntryListFilter<T> implements InitializingBean, En
}
}
}
return accepted;
}
public void afterPropertiesSet() throws Exception {
// its all you!
}
/**
* subclasses must implement this method
*/
public abstract boolean accept(T entry);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
@@ -16,18 +16,19 @@
package org.springframework.integration.file.entries;
/**
* Simple NOOP implementation for {@link org.springframework.integration.file.entries.EntryListFilter} implementation.
* Suitable as a default in implementations.
* Simple NO-OP implementation of {@link org.springframework.integration.file.entries.EntryListFilter}.
* Suitable as a default.
*
* @author Iwein Fuld
* @author Josh Long
* @param <T>
*/
public class AcceptAllEntryListFilter<T> extends AbstractEntryListFilter<T> {
@Override
public boolean accept(T t) {
public boolean accept(T entry) {
return true;
}
}

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* {@link EntryListFilter} that passes files only one time. This can
* conveniently be used to prevent duplication of files, as is done in
@@ -30,16 +30,18 @@ import java.util.concurrent.LinkedBlockingQueue;
* @since 1.0.0
*/
public class AcceptOnceEntryFileListFilter<T> extends AbstractEntryListFilter<T> {
private final Queue<T> seen;
private final Object monitor = new Object();
/**
* Creates an {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} that is based on a bounded queue. If the
* queue overflows, files that fall out will be passed through this filter
* again if passed to the {@link #filterEntries(Object[])} method.
* Creates an {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter}
* that is based on a bounded queue. If the queue overflows, files that fall out will be passed
* through this filter again if passed to the {@link #filterEntries(Object[])} method.
*
* @param maxCapacity the maximum number of Files to maintain in the 'seen'
* queue.
* @param maxCapacity the maximum number of Files to maintain in the 'seen' queue.
*/
public AcceptOnceEntryFileListFilter(int maxCapacity) {
this.seen = new LinkedBlockingQueue<T>(maxCapacity);
@@ -52,18 +54,18 @@ public class AcceptOnceEntryFileListFilter<T> extends AbstractEntryListFilter<T>
this.seen = new LinkedBlockingQueue<T>();
}
public boolean accept(T pathname) {
synchronized (this.monitor) {
if (seen.contains(pathname)) {
if (this.seen.contains(pathname)) {
return false;
}
if (!seen.offer(pathname)) {
seen.poll();
seen.add(pathname);
if (!this.seen.offer(pathname)) {
this.seen.poll();
this.seen.add(pathname);
}
return true;
}
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
import org.springframework.beans.factory.InitializingBean;
@@ -30,8 +31,10 @@ import java.util.*;
* @param <T>
*/
public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
private final Set<EntryListFilter<T>> fileFilters;
public CompositeEntryListFilter() {
this.fileFilters = new LinkedHashSet<EntryListFilter<T>>();
}
@@ -40,23 +43,9 @@ public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
this.fileFilters = new LinkedHashSet<EntryListFilter<T>>(fileFilters);
}
@SuppressWarnings("unchecked")
public List<T> filterEntries(T[] entries) {
Assert.notNull(entries, "'files' should not be null");
List<T> leftOver = Arrays.asList(entries);
for (EntryListFilter<T> fileFilter : this.fileFilters) {
T[] ts = (T[]) leftOver.toArray();
leftOver = fileFilter.filterEntries(ts);
}
return leftOver;
}
@SuppressWarnings("unchecked") //to please the eclipse compiler
public CompositeEntryListFilter<T> addFilter(EntryListFilter<T> filter) {
return this.addFilters(filter);
return this.addFilters(Collections.singletonList(filter));
}
/**
@@ -76,19 +65,31 @@ public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
* @param filtersToAdd a list of filters to add
* @return this CompositeEntryListFilter instance with the added filters
*/
@SuppressWarnings("unchecked")
public CompositeEntryListFilter<T> addFilters(Collection<? extends EntryListFilter<T>> filtersToAdd) {
for (EntryListFilter<? extends T> elf : filtersToAdd)
for (EntryListFilter<? extends T> elf : filtersToAdd) {
if (elf instanceof InitializingBean) {
try {
((InitializingBean) elf).afterPropertiesSet();
} catch (Exception e) {
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
this.fileFilters.addAll(filtersToAdd);
return this;
}
@SuppressWarnings("unchecked")
public List<T> filterEntries(T[] entries) {
Assert.notNull(entries, "'files' should not be null");
List<T> leftOver = Arrays.asList(entries);
for (EntryListFilter<T> fileFilter : this.fileFilters) {
T[] ts = (T[]) leftOver.toArray();
leftOver = fileFilter.filterEntries(ts);
}
return leftOver;
}
}

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
import java.util.List;
/**
* Strategy interface for filtering entries representing files on a local or remote file system. This is a generic
* variant of FileListFilter that also works with references to remote files.
@@ -26,16 +26,15 @@ import java.util.List;
*
* @author Josh Long
* @author Iwein Fuld
*
* @since 2.0.0
*
* @since 2.0
* @see org.springframework.integration.file.filters.FileListFilter
*/
public interface EntryListFilter<T> {
/**
* Filters out entries and returns the entries that are left in a list, or an
* empty list when a null is passed in.
* empty list when null is passed in.
*/
List<T> filterEntries(T[] entries);
}

View File

@@ -13,22 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
/**
* Responsible for coercing a String identification out of the T entry.
*
* @author Josh Long
* @param <T> the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files)
* @param <T> the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files)
*/
public interface EntryNamer<T> {
/**
* This is the one place I couldn't spackle over the interface differences between an FTPFile (FTP adapter), File (File adapter), and LsEntry (SFTP adapter)
* with generics alone. So we have a typed strategy implementation for accessing a property ....
* with generics alone. So we have a typed strategy implementation for accessing a property....
*
* @param entry the entry in a file system listing
* @return the String name that might be used to reference that entry or to do regular expression checks against
*/
String nameOf(T entry);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
@@ -18,16 +18,16 @@ package org.springframework.integration.file.entries;
import java.io.File;
/**
* {@link java.io.File} implementation of the {@link org.springframework.integration.file.entries.EntryNamer} strategy.
* <p/>
* This part feels a little over-engineered...
*
* {@link java.io.File}-based implementation of the {@link EntryNamer} strategy.
*
* @author Josh Long
* @since 2.0
*/
public class FileEntryNamer implements EntryNamer<File> {
public String nameOf(File entry) {
return (entry != null) ? entry.getName() : null;
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.entries;
import org.springframework.beans.factory.InitializingBean;
@@ -21,7 +22,6 @@ import org.springframework.util.StringUtils;
import java.util.regex.Pattern;
/**
* Filters a listing of entries (T) by qualifying their 'name' (as determined by {@link org.springframework.integration.file.entries.EntryNamer})
* against a regular expression (an instance of {@link java.util.regex.Pattern})
@@ -29,13 +29,16 @@ import java.util.regex.Pattern;
* @author Iwein Fuld
* @author Josh Long
* @param <T> the type of entry
*
* @since 2.0.0
* @since 2.0
*/
public class PatternMatchingEntryListFilter<T> extends AbstractEntryListFilter<T> implements InitializingBean {
private Pattern pattern;
private String patternExpression;
private EntryNamer<T> entryNamer;
private volatile EntryNamer<T> entryNamer;
private volatile Pattern pattern;
private volatile String patternExpression;
public PatternMatchingEntryListFilter(EntryNamer<T> en, String p) {
this.entryNamer = en;
@@ -47,6 +50,11 @@ public class PatternMatchingEntryListFilter<T> extends AbstractEntryListFilter<T
this.pattern = p;
}
public void setEntryNamer(EntryNamer<T> entryNamer) {
this.entryNamer = entryNamer;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
@@ -64,11 +72,8 @@ public class PatternMatchingEntryListFilter<T> extends AbstractEntryListFilter<T
}
@Override
public boolean accept(T t) {
return (t != null) && this.pattern.matcher(this.entryNamer.nameOf(t)).matches();
public boolean accept(T entry) {
return (entry != null) && this.pattern.matcher(this.entryNamer.nameOf(entry)).matches();
}
public void setEntryNamer(EntryNamer<T> entryNamer) {
this.entryNamer = entryNamer;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
@@ -18,10 +18,9 @@ package org.springframework.integration.file.entries;
import org.springframework.util.Assert;
/**
* this simply takes an {@link org.springframework.integration.file.entries.EntryListFilter}
* and produces an object that can field just <b>one</b> argument instea of an array
* This simply takes an {@link org.springframework.integration.file.entries.EntryListFilter}
* and produces an object that can field just <b>one</b> argument instead of an array.
*
* @author Josh Long
*/
@@ -30,17 +29,19 @@ public class SingleEntryAdaptingEntryListFilter<T> extends AbstractEntryListFilt
/**
* the {@link org.springframework.integration.file.entries.EntryListFilter} that you'd like to delegate to
*/
private volatile EntryListFilter<T> entryFilter;
private volatile EntryListFilter<T> entryListFilter;
public SingleEntryAdaptingEntryListFilter(EntryListFilter<T> ef) {
this.entryFilter = ef;
Assert.notNull(this.entryFilter, "the entryFilter can't be null");
public SingleEntryAdaptingEntryListFilter(EntryListFilter<T> entryListFilter) {
Assert.notNull(entryListFilter, "entryListFilter must not be null");
this.entryListFilter = entryListFilter;
}
@Override
@SuppressWarnings("unchecked")
public boolean accept(T t) {
T[] ts = (T[]) new Object[]{t};
return this.entryFilter.filterEntries(ts).size() == 1;
return this.entryListFilter.filterEntries(ts).size() == 1;
}
}