git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1207412 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA5
@@ -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> |
@@ -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"); | |||
} | |||
} | |||
} |
@@ -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())); | |||
} | |||
} |