Tidy up the xssf models stuff, by pushing more of the logic onto XSSFWorkbook

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@637688 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-03-16 23:30:51 +00:00
parent fe2cd2d286
commit 86bac45ee8
6 changed files with 151 additions and 129 deletions

View File

@ -39,9 +39,4 @@ public interface SharedStringSource {
* @return The 0-based position of the newly added string.
*/
public int putSharedString(String s);
/**
* Write back out
*/
public void save() throws IOException;
}

View File

@ -16,14 +16,10 @@
==================================================================== */
package org.apache.poi.ss.usermodel;
import java.io.IOException;
public interface StylesSource {
public String getNumberFormatAt(long idx);
public long putNumberFormat(String fmt);
/**
* Write back out
*/
public void save() throws IOException;
public Font getFontAt(long idx);
public long putFont(Font font);
}

View File

@ -25,7 +25,6 @@ import java.util.LinkedList;
import org.apache.poi.ss.usermodel.SharedStringSource;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxml4j.opc.PackagePart;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
@ -34,32 +33,28 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
/**
* Table of strings shared across all sheets in a workbook.
*
* FIXME: I don't like having a dependency on PackagePart (from OpenXML4J) in model classes.
* I'd rather let Workbook keep track of all part-document relationships and keep all other
* classes clean. -- Ugo
*
* @version $Id$
*/
public class SharedStringsTable implements SharedStringSource, XSSFModel {
private final LinkedList<String> strings = new LinkedList<String>();
private SstDocument doc;
private PackagePart part;
/**
* Create a new SharedStringsTable by reading it from a PackagePart.
* Create a new SharedStringsTable, by reading it
* from the InputStream of a PackagePart.
*
* @param part The PackagePart to read.
* @param is The input stream containing the XML document.
* @throws IOException if an error occurs while reading.
*/
public SharedStringsTable(PackagePart part) throws IOException {
this.part = part;
InputStream is = part.getInputStream();
try {
readFrom(is);
} finally {
if (is != null) is.close();
}
public SharedStringsTable(InputStream is) throws IOException {
readFrom(is);
}
/**
* Create a new, empty SharedStringsTable
*/
public SharedStringsTable() {
doc = SstDocument.Factory.newInstance();
}
/**
@ -70,7 +65,7 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
*/
public void readFrom(InputStream is) throws IOException {
try {
SstDocument doc = SstDocument.Factory.parse(is);
doc = SstDocument.Factory.parse(is);
for (CTRst rst : doc.getSst().getSiArray()) {
strings.add(rst.getT());
}
@ -91,20 +86,6 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
return strings.size() - 1;
}
/**
* Save this table to its own PackagePart.
*
* @throws IOException if an error occurs while writing.
*/
public void save() throws IOException {
OutputStream out = this.part.getOutputStream();
try {
writeTo(out);
} finally {
out.close();
}
}
/**
* Write this table out as XML.
*

View File

@ -25,13 +25,14 @@ import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map.Entry;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.StylesSource;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxml4j.opc.PackagePart;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFonts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;;
@ -40,10 +41,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;;
/**
* Table of styles shared across all sheets in a workbook.
*
* FIXME: I don't like having a dependency on PackagePart (from OpenXML4J) in model classes.
* I'd rather let Workbook keep track of all part-document relationships and keep all other
* classes clean. -- Ugo
*
* @version $Id: SharedStringsTable.java 612495 2008-01-16 16:08:22Z ugo $
*/
public class StylesTable implements StylesSource, XSSFModel {
@ -52,23 +49,28 @@ public class StylesTable implements StylesSource, XSSFModel {
private final LinkedList<CTFill> fills = new LinkedList<CTFill>();
private final LinkedList<CTBorder> borders = new LinkedList<CTBorder>();
private PackagePart part;
/**
* The first style id available for use as a custom style
*/
public static final long FIRST_CUSTOM_STYLE_ID = 165;
private StyleSheetDocument doc;
/**
* Create a new StylesTable by reading it from a PackagePart.
* Create a new StylesTable, by reading it from
* the InputStream of a a PackagePart.
*
* @param part The PackagePart to read.
* @param is The input stream containing the XML document.
* @throws IOException if an error occurs while reading.
*/
public StylesTable(PackagePart part) throws IOException {
this.part = part;
InputStream is = part.getInputStream();
try {
readFrom(is);
} finally {
if (is != null) is.close();
}
public StylesTable(InputStream is) throws IOException {
readFrom(is);
}
/**
* Create a new, empty StylesTable
*/
public StylesTable() {
doc = StyleSheetDocument.Factory.newInstance();
}
/**
@ -106,7 +108,6 @@ public class StylesTable implements StylesSource, XSSFModel {
public String getNumberFormatAt(long idx) {
return numberFormats.get(idx);
}
public synchronized long putNumberFormat(String fmt) {
if (numberFormats.containsValue(fmt)) {
// Find the key, and return that
@ -120,7 +121,7 @@ public class StylesTable implements StylesSource, XSSFModel {
}
// Find a spare key, and add that
long newKey = 1;
long newKey = FIRST_CUSTOM_STYLE_ID;
while(numberFormats.containsKey(newKey)) {
newKey++;
}
@ -128,6 +129,15 @@ public class StylesTable implements StylesSource, XSSFModel {
return newKey;
}
public Font getFontAt(long idx) {
// TODO
return null;
}
public synchronized long putFont(Font font) {
// TODO
return -1;
}
/**
* For unit testing only
*/
@ -154,20 +164,6 @@ public class StylesTable implements StylesSource, XSSFModel {
}
/**
* Save this table to its own PackagePart.
*
* @throws IOException if an error occurs while writing.
*/
public void save() throws IOException {
OutputStream out = this.part.getOutputStream();
try {
writeTo(out);
} finally {
out.close();
}
}
/**
* Write this table out as XML.
*
@ -193,7 +189,12 @@ public class StylesTable implements StylesSource, XSSFModel {
doc.getStyleSheet().setNumFmts(formats);
// Fonts
// TODO
CTFonts fnts = CTFonts.Factory.newInstance();
fnts.setCount(fonts.size());
fnts.setFontArray(
fonts.toArray(new CTFont[fonts.size()])
);
doc.getStyleSheet().setFonts(fnts);
// Fills
// TODO

View File

@ -18,7 +18,9 @@
package org.apache.poi.xssf.usermodel;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -65,22 +67,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
public class XSSFWorkbook extends POIXMLDocument implements Workbook {
public static class XSSFRelation {
private String TYPE;
private String REL;
private String DEFAULT_NAME;
private Class<? extends XSSFModel> CLASS;
private XSSFRelation(String TYPE, String REL, String DEFAULT_NAME, Class<? extends XSSFModel> CLASS) {
this.TYPE = TYPE;
this.REL = REL;
this.DEFAULT_NAME = DEFAULT_NAME;
this.CLASS = CLASS;
}
public String getContentType() { return TYPE; }
public String getRelation() { return REL; }
public String getDefaultFileName() { return DEFAULT_NAME; }
}
public static final XSSFRelation WORKSHEET = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
@ -112,6 +98,70 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
null
);
public static class XSSFRelation {
private String TYPE;
private String REL;
private String DEFAULT_NAME;
private Class<? extends XSSFModel> CLASS;
private XSSFRelation(String TYPE, String REL, String DEFAULT_NAME, Class<? extends XSSFModel> CLASS) {
this.TYPE = TYPE;
this.REL = REL;
this.DEFAULT_NAME = DEFAULT_NAME;
this.CLASS = CLASS;
}
public String getContentType() { return TYPE; }
public String getRelation() { return REL; }
public String getDefaultFileName() { return DEFAULT_NAME; }
/**
* Load, off the specified core part
*/
private XSSFModel load(PackagePart corePart) throws Exception {
Constructor<? extends XSSFModel> c = CLASS.getConstructor(InputStream.class);
XSSFModel model = null;
PackageRelationshipCollection prc =
corePart.getRelationshipsByType(REL);
Iterator<PackageRelationship> it = prc.iterator();
if(it.hasNext()) {
PackageRelationship rel = it.next();
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
PackagePart part = corePart.getPackage().getPart(relName);
InputStream is = part.getInputStream();
try {
model = c.newInstance(is);
} finally {
is.close();
}
} else {
log.log(POILogger.WARN, "No part " + DEFAULT_NAME + " found");
}
return model;
}
/**
* Save, with the default name
*/
private void save(XSSFModel model, PackagePart corePart) throws IOException {
save(model, corePart, DEFAULT_NAME);
}
/**
* Save, with the specified name
*/
private void save(XSSFModel model, PackagePart corePart, String name) throws IOException {
PackagePartName ppName = null;
try {
ppName = PackagingURIHelper.createPartName(name);
} catch(InvalidFormatException e) {
throw new IllegalStateException(e);
}
corePart.addRelationship(ppName, TargetMode.INTERNAL, REL);
PackagePart part = corePart.getPackage().createPart(ppName, TYPE);
OutputStream out = part.getOutputStream();
model.writeTo(out);
out.close();
}
}
private CTWorkbook workbook;
private List<XSSFSheet> sheets = new LinkedList<XSSFSheet>();
@ -138,34 +188,22 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
WorkbookDocument doc = WorkbookDocument.Factory.parse(getCorePart().getInputStream());
this.workbook = doc.getWorkbook();
PackageRelationshipCollection prc;
Iterator<PackageRelationship> it;
// Load shared strings
prc = getCorePart().getRelationshipsByType(SHARED_STRINGS.getRelation());
it = prc.iterator();
if (it.hasNext()) {
PackageRelationship rel = it.next();
PackagePart part = getTargetPart(rel);
this.sharedStringSource = new SharedStringsTable(part);
} else {
log.log(POILogger.WARN, "No shared strings part found");
}
// Load styles source
prc = getCorePart().getRelationshipsByType(STYLES.getRelation());
it = prc.iterator();
if (it.hasNext()) {
PackageRelationship rel = it.next();
PackagePart part = getTargetPart(rel);
this.stylesSource = new StylesTable(part);
} else {
log.log(POILogger.WARN, "No styles part found");
try {
// Load shared strings
this.sharedStringSource = (SharedStringSource)
SHARED_STRINGS.load(getCorePart());
// Load styles source
this.stylesSource = (StylesSource)
STYLES.load(getCorePart());
} catch(Exception e) {
throw new IOException(e.getMessage());
}
// Load individual sheets
for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) {
PackagePart part = getPackagePart(ctSheet);
if (part == null) {
log.log(POILogger.WARN, "Sheet with name " + ctSheet.getName() + " was defined, but didn't exist, skipping");
continue;
}
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
@ -572,21 +610,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
// Write shared strings and styles
if(sharedStringSource != null) {
SharedStringsTable sst = (SharedStringsTable)sharedStringSource;
PackagePartName sstName = PackagingURIHelper.createPartName(SHARED_STRINGS.getDefaultFileName());
corePart.addRelationship(sstName, TargetMode.INTERNAL, SHARED_STRINGS.getRelation());
PackagePart sstPart = pkg.createPart(sstName, SHARED_STRINGS.getContentType());
out = sstPart.getOutputStream();
sst.writeTo(out);
out.close();
SHARED_STRINGS.save(sst, corePart);
}
if(stylesSource != null) {
StylesTable st = (StylesTable)stylesSource;
PackagePartName stName = PackagingURIHelper.createPartName(STYLES.getDefaultFileName());
corePart.addRelationship(stName, TargetMode.INTERNAL, STYLES.getRelation());
PackagePart stPart = pkg.createPart(stName, STYLES.getContentType());
out = stPart.getOutputStream();
st.writeTo(out);
out.close();
STYLES.save(st, corePart);
}
// All done

View File

@ -31,8 +31,17 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
public class TestXSSFWorkbook extends TestCase {
public void testGetSheetIndex() {
public TestXSSFWorkbook(String name) {
super(name);
// Use system out logger
System.setProperty(
"org.apache.poi.util.POILogger",
"org.apache.poi.util.SystemOutLogger"
);
}
public void testGetSheetIndex() {
XSSFWorkbook workbook = new XSSFWorkbook();
Sheet sheet1 = workbook.createSheet("sheet1");
Sheet sheet2 = workbook.createSheet("sheet2");
@ -127,7 +136,7 @@ public class TestXSSFWorkbook extends TestCase {
Sheet sheet2 = workbook.createSheet("sheet2");
Sheet sheet3 = workbook.createSheet("sheet3");
File file = File.createTempFile("poi-", ".xlsx");
System.out.println("Saving to " + file.getAbsolutePath());
System.out.println("Saving newly created file to " + file.getAbsolutePath());
OutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();
@ -194,5 +203,17 @@ public class TestXSSFWorkbook extends TestCase {
assertEquals(2, st._getFillsSize());
// Has 1 border
assertEquals(1, st._getBordersSize());
// Add two more styles
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 8,
st.putNumberFormat("testFORMAT"));
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 8,
st.putNumberFormat("testFORMAT"));
assertEquals(StylesTable.FIRST_CUSTOM_STYLE_ID + 9,
st.putNumberFormat("testFORMAT2"));
assertEquals(10, st._getNumberFormatSize());
// Save, load back in again, and check
// TODO
}
}