]> source.dussan.org Git - poi.git/commitdiff
Add a POIFS Helper FilteringDirectoryNode, which wraps a DirectoryEntry and allows...
authorNick Burch <nick@apache.org>
Mon, 28 Nov 2011 16:44:16 +0000 (16:44 +0000)
committerNick Burch <nick@apache.org>
Mon, 28 Nov 2011 16:44:16 +0000 (16:44 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1207412 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java [new file with mode: 0644]
src/testcases/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java [new file with mode: 0644]

index 4741a2e3416582737888befb1a798cb4eba826d7..36754893384d041a31bc9901758f5ba8508ab0d2 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta5" date="2011-??-??">
+           <action dev="poi-developers" type="add">POIFS Helper FilteringDirectoryNode, which wraps a DirectoryEntry and allows certain parts to be ignored</action>
            <action dev="poi-developers" type="fix">52209 - fixed inserting multiple pictures in XSLF </action>
            <action dev="poi-developers" type="fix">51803 - fixed HSLF TextExtractor to extract content from master slide </action>
            <action dev="poi-developers" type="fix">52190 - null check on XWPF setFontFamily</action>
diff --git a/src/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java
new file mode 100644 (file)
index 0000000..737f8d9
--- /dev/null
@@ -0,0 +1,211 @@
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.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;
+
+/**
+ * A DirectoryEntry filter, which exposes another
+ *  DirectoryEntry less certain parts.
+ * This is typically used when copying or comparing
+ *  Filesystems. 
+ */
+public class FilteringDirectoryNode implements DirectoryEntry
+{
+   /**
+    * The names of our entries to exclude
+    */
+   private Set<String> excludes;
+   /**
+    * Excludes of our child directories
+    */
+   private Map<String,List<String>> childExcludes;
+   
+   private DirectoryEntry directory;
+   
+   /**
+    * Creates a filter round the specified directory, which
+    *  will exclude entries such as "MyNode" and "MyDir/IgnoreNode".
+    * The excludes can stretch into children, if they contain a /.
+    *  
+    * @param entry The Directory to filter
+    * @param excludes The Entries to exclude
+    */
+   public FilteringDirectoryNode(DirectoryEntry directory, Collection<String> excludes) {
+      this.directory = directory;
+      
+      // Process the excludes
+      this.excludes = new HashSet<String>();
+      this.childExcludes = new HashMap<String, List<String>>();
+      for (String excl : excludes) {
+         int splitAt = excl.indexOf('/');
+         if (splitAt == -1) {
+            // Applies to us
+            this.excludes.add(excl);
+         } else {
+            // Applies to a child
+            String child = excl.substring(0, splitAt);
+            String childExcl = excl.substring(splitAt+1);
+            if (! this.childExcludes.containsKey(child)) {
+               this.childExcludes.put(child, new ArrayList<String>());
+            }
+            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 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");
+      }
+   }
+}
\ No newline at end of file
diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java b/src/testcases/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java
new file mode 100644 (file)
index 0000000..bef0281
--- /dev/null
@@ -0,0 +1,172 @@
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.poi.poifs.filesystem;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * Class to test FilteringDirectoryNode functionality
+ */
+public final class TestFilteringDirectoryNode extends TestCase {
+    private POIFSFileSystem fs;
+    private DirectoryEntry dirA;
+    private DirectoryEntry dirAA;
+    private DirectoryEntry dirB;
+    private DocumentEntry eRoot;
+    private DocumentEntry eA;
+    private DocumentEntry eAA;
+    
+    @Override
+    protected void setUp() throws Exception {
+       fs = new POIFSFileSystem();
+       dirA = fs.createDirectory("DirA");
+       dirB = fs.createDirectory("DirB");
+       dirAA = dirA.createDirectory("DirAA");
+       eRoot = fs.getRoot().createDocument("Root", new ByteArrayInputStream(new byte[] {}));
+       eA  = dirA.createDocument("NA", new ByteArrayInputStream(new byte[] {}));
+       eAA = dirAA.createDocument("NAA", new ByteArrayInputStream(new byte[] {}));
+    }
+    
+    public void testNoFiltering() throws Exception {
+       FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), new HashSet<String>());
+       assertEquals(3, d.getEntryCount());
+       assertEquals(dirA.getName(), d.getEntry(dirA.getName()).getName());
+       
+       assertEquals(true, d.getEntry(dirA.getName()).isDirectoryEntry());
+       assertEquals(false, d.getEntry(dirA.getName()).isDocumentEntry());
+       
+       assertEquals(true, d.getEntry(dirB.getName()).isDirectoryEntry());
+       assertEquals(false, d.getEntry(dirB.getName()).isDocumentEntry());
+       
+       assertEquals(false, d.getEntry(eRoot.getName()).isDirectoryEntry());
+       assertEquals(true, d.getEntry(eRoot.getName()).isDocumentEntry());
+       
+       Iterator<Entry> i = d.getEntries();
+       assertEquals(dirA, i.next());
+       assertEquals(dirB, i.next());
+       assertEquals(eRoot, i.next());
+       assertEquals(null, i.next());
+    }
+    
+    public void testChildFiltering() throws Exception {
+       List<String> excl = Arrays.asList(new String[] {"NotThere","AlsoNotThere", eRoot.getName()});
+       FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
+       
+       assertEquals(2, d.getEntryCount());
+       assertEquals(true, d.hasEntry(dirA.getName()));
+       assertEquals(true, d.hasEntry(dirB.getName()));
+       assertEquals(false, d.hasEntry(eRoot.getName()));
+       
+       assertEquals(dirA, d.getEntry(dirA.getName()));
+       assertEquals(dirB, d.getEntry(dirB.getName()));
+       try {
+          d.getEntry(eRoot.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       
+       Iterator<Entry> i = d.getEntries();
+       assertEquals(dirA, i.next());
+       assertEquals(dirB, i.next());
+       assertEquals(null, i.next());
+       
+       
+       // Filter more
+       excl = Arrays.asList(new String[] {"NotThere","AlsoNotThere", eRoot.getName(), dirA.getName()});
+       d = new FilteringDirectoryNode(fs.getRoot(), excl);
+       
+       assertEquals(1, d.getEntryCount());
+       assertEquals(false, d.hasEntry(dirA.getName()));
+       assertEquals(true, d.hasEntry(dirB.getName()));
+       assertEquals(false, d.hasEntry(eRoot.getName()));
+       
+       try {
+          d.getEntry(dirA.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       assertEquals(dirB, d.getEntry(dirB.getName()));
+       try {
+          d.getEntry(eRoot.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       
+       i = d.getEntries();
+       assertEquals(dirB, i.next());
+       assertEquals(null, i.next());
+       
+       
+       // Filter everything
+       excl = Arrays.asList(new String[] {"NotThere", eRoot.getName(), dirA.getName(), dirB.getName()});
+       d = new FilteringDirectoryNode(fs.getRoot(), excl);
+       
+       assertEquals(0, d.getEntryCount());
+       assertEquals(false, d.hasEntry(dirA.getName()));
+       assertEquals(false, d.hasEntry(dirB.getName()));
+       assertEquals(false, d.hasEntry(eRoot.getName()));
+       
+       try {
+          d.getEntry(dirA.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       try {
+          d.getEntry(dirB.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       try {
+          d.getEntry(eRoot.getName());
+          fail("Should be filtered");
+       } catch(FileNotFoundException e) {}
+       
+       i = d.getEntries();
+       assertEquals(null, i.next());
+    }
+    
+    public void testNestedFiltering() throws Exception {
+       List<String> excl = Arrays.asList(new String[] {
+             dirA.getName()+"/"+"MadeUp",
+             dirA.getName()+"/"+eA.getName(),
+             dirA.getName()+"/"+dirAA.getName()+"/Test",
+             eRoot.getName()
+       });
+       FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
+       
+       // Check main
+       assertEquals(2, d.getEntryCount());
+       assertEquals(true, d.hasEntry(dirA.getName()));
+       assertEquals(true, d.hasEntry(dirB.getName()));
+       assertEquals(false, d.hasEntry(eRoot.getName()));
+       
+       // Check filtering down
+       assertEquals(true, d.getEntry(dirA.getName()) instanceof FilteringDirectoryNode);
+       assertEquals(false, d.getEntry(dirB.getName()) instanceof FilteringDirectoryNode);
+       
+       DirectoryEntry fdA = (DirectoryEntry)d.getEntry(dirA.getName()); 
+       assertEquals(false, fdA.hasEntry(eA.getName()));
+       assertEquals(true, fdA.hasEntry(dirAA.getName()));
+       
+       DirectoryEntry fdAA = (DirectoryEntry)fdA.getEntry(dirAA.getName()); 
+       assertEquals(true, fdAA.hasEntry(eAA.getName()));
+    }
+}