package org.apache.poi.poifs.filesystem;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hpsf.ClassID;
public class FilteringDirectoryNode implements DirectoryEntry
{
private Set<String> excludes;
private Map<String,List<String>> childExcludes;
private DirectoryEntry directory;
public FilteringDirectoryNode(DirectoryEntry directory, Collection<String> excludes) {
if (directory == null) {
throw new IllegalArgumentException("directory cannot be null");
}
this.directory = directory;
this.excludes = new HashSet<>();
this.childExcludes = new HashMap<>();
for (String excl : excludes) {
int splitAt = excl.indexOf('/');
if (splitAt == -1) {
this.excludes.add(excl);
} else {
String child = excl.substring(0, splitAt);
String childExcl = excl.substring(splitAt+1);
if (! this.childExcludes.containsKey(child)) {
this.childExcludes.put(child, new ArrayList<>());
}
this.childExcludes.get(child).add(childExcl);
}
}
}
public DirectoryEntry createDirectory(String name) throws IOException {
return directory.createDirectory(name);
}
public DocumentEntry createDocument(String name, InputStream stream)
throws IOException {
return directory.createDocument(name, stream);
}
public DocumentEntry createDocument(String name, int size,
POIFSWriterListener writer) throws IOException {
return directory.createDocument(name, size, writer);
}
public Iterator<Entry> getEntries() {
return new FilteringIterator();
}
public Iterator<Entry> iterator() {
return getEntries();
}
public int getEntryCount() {
int size = directory.getEntryCount();
for (String excl : excludes) {
if (directory.hasEntry(excl)) {
size--;
}
}
return size;
}
public Set<String> getEntryNames() {
Set<String> names = new HashSet<>();
for (String name : directory.getEntryNames()) {
if (!excludes.contains(name)) {
names.add(name);
}
}
return names;
}
public boolean isEmpty() {
return (getEntryCount() == 0);
}
public boolean hasEntry(String name) {
if (excludes.contains(name)) {
return false;
}
return directory.hasEntry(name);
}
public Entry getEntry(String name) throws FileNotFoundException {
if (excludes.contains(name)) {
throw new FileNotFoundException(name);
}
Entry entry = directory.getEntry(name);
return wrapEntry(entry);
}
private Entry wrapEntry(Entry entry) {
String name = entry.getName();
if (childExcludes.containsKey(name) && entry instanceof DirectoryEntry) {
return new FilteringDirectoryNode(
(DirectoryEntry)entry, childExcludes.get(name));
}
return entry;
}
public ClassID getStorageClsid() {
return directory.getStorageClsid();
}
public void setStorageClsid(ClassID clsidStorage) {
directory.setStorageClsid(clsidStorage);
}
public boolean delete() {
return directory.delete();
}
public boolean renameTo(String newName) {
return directory.renameTo(newName);
}
public String getName() {
return directory.getName();
}
public DirectoryEntry getParent() {
return directory.getParent();
}
public boolean isDirectoryEntry() {
return true;
}
public boolean isDocumentEntry() {
return false;
}
private class FilteringIterator implements Iterator<Entry> {
private Iterator<Entry> parent;
private Entry next;
private FilteringIterator() {
parent = directory.getEntries();
locateNext();
}
private void locateNext() {
next = null;
Entry e;
while (parent.hasNext() && next == null) {
e = parent.next();
if (! excludes.contains(e.getName())) {
next = wrapEntry(e);
}
}
}
public boolean hasNext() {
return (next != null);
}
public Entry next() {
Entry e = next;
locateNext();
return e;
}
public void remove() {
throw new UnsupportedOperationException("Remove not supported");
}
}
}