@SuppressWarnings(value = "unchecked")
public final class Selector implements Closeable, Iterable<FileView> {
private List headers;
private Extractor extractor;
private Set workSet;
public Selector(Extractor extractor) {
this(extractor, extractor.getFileHeaders());
}
private Selector(Extractor extractor, List headers) {
this.headers = headers;
this.extractor = extractor;
this.workSet = new LinkedHashSet(headers.size() * 2);
}
public boolean isEmpty() {
return headers.isEmpty();
}
public int selectedSize() {
return workSet.size();
}
public int size() {
return headers.size();
}
public void clear() {
workSet.clear();
}
public void close() throws IOException {
if (extractor == null) {
return;
}
extractor.close();
headers = null;
workSet = null;
extractor = null;
}
public Selector subSelector() {
if (workSet.size() == headers.size()) {
workSet.clear();
return this;
} else if (workSet.size() == 0) {
return new Selector(extractor, Collections.EMPTY_LIST);
}
return new Selector(extractor, new ArrayList(workSet));
}
public Selector inverseSelector() {
if (workSet.size() == 0) {
return this;
} else if (workSet.size() == headers.size()) {
return new Selector(extractor, Collections.EMPTY_LIST);
}
//removing in arraylists is painfull
LinkedList arr = new LinkedList(headers);
arr.removeAll(workSet);
return new Selector(extractor, arr);
}
public Selector selectAll() {
for (Object h : headers) {
workSet.add(h);
}
return this;
}
public Selector selectByCRC32(long crc32) {
for (Object h : headers) {
Long crc = extractor.getCRC32(h);
if (crc != null && (crc & 0X00000000ffffffffL) == (crc32 & 0X00000000ffffffffL)) {
workSet.add(h);
}
}
return this;
}
public Selector selectByCompressedFileSize(Inequality i, long size) {
if (i == null) {
return this;
}
for (Object h : headers) {
Long fs = extractor.getCompressedFileSize(h);
if (i.TEST(fs, size)) {
workSet.add(h);
}
}
return this;
}
public Selector selectByFileSize(Inequality i, long size) {
if (i == null) {
return this;
}
for (Object h : headers) {
Long fs = extractor.getFileSize(h);
if (i.TEST(fs, size)) {
workSet.add(h);
}
}
return this;
}
public Selector selectByModificationDate(Inequality i, DateFormat format, String datePattern) {
if (i == null || format == null || datePattern == null) {
return this;
}
try {
Date givenDate = format.parse(datePattern);
for (Object h : headers) {
Date archiveDate = extractor.getModificationDate(h);
if (archiveDate == null) {
continue;
}
Date comparableDate = format.parse(format.format(archiveDate));
if (i.TEST(comparableDate, givenDate)) {
workSet.add(h);
}
}
} catch (ParseException ex) {
throw new IllegalArgumentException("Formatter can't parse given datePattern", ex);
}
return this;
}
public Selector selectByModificationDate(Inequality i, Date date) {
if (i == null || date == null) {
return this;
}
for (Object h : headers) {
Date archiveDate = extractor.getModificationDate(h);
if (archiveDate == null) {
continue;
}
if (i.TEST(archiveDate, date)) {
workSet.add(h);
}
}
return this;
}
public Selector selectByName(String name, boolean caseSensitive) {
if (name == null) {
return this;
//Archived name is never null...
}
if (caseSensitive) {
for (Object h : headers) {
if (extractor.getFileName(h).equals(name)) {
workSet.add(h);
}
}
} else {
for (Object h : headers) {
if (extractor.getFileName(h).toLowerCase(Locale.ENGLISH).equals(name.toLowerCase(Locale.ENGLISH))) {
workSet.add(h);
}
}
}
return this;
}
public Selector selectByName(Inequality i, String s) {
if (i == null || s == null) {
return this;
//name is never null...
}
Comparator<String> natural = Strings.getNaturalComparator();
for (Object h : headers) {
if (i.TEST(extractor.getFileName(h), s, natural)) {
workSet.add(h);
}
}
return this;
}
public Selector selectByRegex(String regex) {
if (regex == null) {
return this;
//name never null
}
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher("");
for (Object h : headers) {
m.reset(extractor.getFileName(h));
if (m.matches()) {
workSet.add(h);
}
}
return this;
}
public Selector selectByRegex(String regex, int flags) {
if (regex == null) {
return this;
//name never null
}
Pattern p = Pattern.compile(regex, flags);
Matcher m = p.matcher("");
for (Object h : headers) {
m.reset(extractor.getFileName(h));
if (m.matches()) {
workSet.add(h);
}
}
return this;
}
public Selector selectBySuffix(String suffix, boolean caseSensitive) {
if (suffix == null) {
return this;
}
//Archived name is never null...
if (caseSensitive) {
for (Object h : headers) {
if (extractor.getFilePath(h).endsWith(suffix)) {
workSet.add(h);
}
}
} else {
for (Object h : headers) {
if (extractor.getFilePath(h).toLowerCase(Locale.ENGLISH).endsWith(suffix.toLowerCase(Locale.ENGLISH))) {
workSet.add(h);
}
}
}
return this;
}
public Selector orderByAscending(FileComparator c) {
Object[] a = workSet.toArray();
Arrays.sort(a, c.getComparator(extractor));
workSet = new LinkedHashSet(a.length * 2);
for (int i = 0; i < a.length; i++) {
workSet.add(a[i]);
}
return this;
}
public FileView getSelected() {
Iterator it = workSet.iterator();
if (it.hasNext()) {
return new FileView(it.next(), extractor);
} else {
return null;
}
}
public FileView getSelectedMax(FileComparator c) {
try {
Object header = Collections.max(workSet, c.getComparator(extractor));
return new FileView(header, extractor);
} catch (NoSuchElementException ex) {
return null;
}
}
public FileView getSelectedMin(FileComparator c) {
try {
Object header = Collections.min(workSet, c.getComparator(extractor));
return new FileView(header, extractor);
} catch (NoSuchElementException ex) {
return null;
}
}
public Selector orderByDescending(FileComparator c) {
Object[] a = workSet.toArray();
Arrays.sort(a, Collections.reverseOrder(c.getComparator(extractor)));
workSet = new LinkedHashSet(a.length * 2);
for (int i = 0; i < a.length; i++) {
workSet.add(a[i]);
}
return this;
}
public ContentsIterator iterator() {
return new ContentsIterator(workSet.iterator(), workSet.size(), extractor);
}
public ContentsIterator iterator(int numberToExtract) {
int toExtract = Math.max(0, Math.min(numberToExtract, workSet.size()));
return new ContentsIterator(workSet.iterator(), toExtract, extractor);
}
public static final class ContentsIterator implements Iterator<FileView>, Iterable<FileView> {
private Iterator headerCopy;
private Extractor extractor;
private int size, index;
private ContentsIterator(Iterator headerCopy, int size, Extractor extractor) {
this.headerCopy = headerCopy;
this.size = size;
this.extractor = extractor;
}
public Iterator<FileView> iterator() {
return this;
}
public boolean hasNext() {
return index < size;
}
public FileView next() {
if (hasNext()) {
index++;
return new FileView(headerCopy.next(), extractor);
} else {
throw new NoSuchElementException();
}
}
public void remove() {
headerCopy.remove();
}
}
}