From fe2cd2d28619b5e8fdae37ea279d12f3de5f4af0 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Sun, 16 Mar 2008 22:44:10 +0000 Subject: [PATCH] Start to tidy up the model loading, to reduce duplicated code, and make it cleaner git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@637680 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/usermodel/SharedStringSource.java | 7 ++ .../apache/poi/ss/usermodel/StylesSource.java | 7 ++ .../poi/xssf/model/SharedStringsTable.java | 2 +- .../apache/poi/xssf/model/StylesTable.java | 6 +- .../org/apache/poi/xssf/model/XSSFModel.java | 26 +++++ .../poi/xssf/usermodel/XSSFWorkbook.java | 100 ++++++++++++++---- .../poi/xssf/usermodel/TestXSSFWorkbook.java | 27 +++++ 7 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 src/ooxml/java/org/apache/poi/xssf/model/XSSFModel.java diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/SharedStringSource.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/SharedStringSource.java index 2f01b227b..6979a7c7e 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/SharedStringSource.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/SharedStringSource.java @@ -17,6 +17,8 @@ package org.apache.poi.ss.usermodel; +import java.io.IOException; + /** * Allows the getting and saving of shared strings */ @@ -37,4 +39,9 @@ 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; } diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/StylesSource.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/StylesSource.java index 2b21ecaac..dc328ff10 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/StylesSource.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/StylesSource.java @@ -16,7 +16,14 @@ ==================================================================== */ 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; } diff --git a/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java b/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java index fd43647cd..33e5bfe81 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java @@ -40,7 +40,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument; * * @version $Id$ */ -public class SharedStringsTable implements SharedStringSource { +public class SharedStringsTable implements SharedStringSource, XSSFModel { private final LinkedList strings = new LinkedList(); diff --git a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java index f96df8e72..122a1b440 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java @@ -46,7 +46,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;; * * @version $Id: SharedStringsTable.java 612495 2008-01-16 16:08:22Z ugo $ */ -public class StylesTable implements StylesSource { +public class StylesTable implements StylesSource, XSSFModel { private final Hashtable numberFormats = new Hashtable(); private final LinkedList fonts = new LinkedList(); private final LinkedList fills = new LinkedList(); @@ -99,6 +99,10 @@ public class StylesTable implements StylesSource { } } + // =========================================================== + // Start of style related getters and setters + // =========================================================== + public String getNumberFormatAt(long idx) { return numberFormats.get(idx); } diff --git a/src/ooxml/java/org/apache/poi/xssf/model/XSSFModel.java b/src/ooxml/java/org/apache/poi/xssf/model/XSSFModel.java new file mode 100644 index 000000000..7fe1083e7 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/model/XSSFModel.java @@ -0,0 +1,26 @@ +/* ==================================================================== + 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.xssf.model; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public interface XSSFModel { + public void readFrom(InputStream is) throws IOException; + public void writeTo(OutputStream out) throws IOException; +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index 4d3a943b3..57d37a404 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -41,6 +41,7 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; +import org.apache.poi.xssf.model.XSSFModel; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; @@ -64,18 +65,52 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument; public class XSSFWorkbook extends POIXMLDocument implements Workbook { - - private static final String WORKSHEET_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"; - - private static final String WORKSHEET_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; - - private static final String SHARED_STRINGS_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; - - private static final String STYLES_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; - - private static final String DRAWING_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"; - - private static final String IMAGE_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; + public static class XSSFRelation { + private String TYPE; + private String REL; + private String DEFAULT_NAME; + private Class CLASS; + private XSSFRelation(String TYPE, String REL, String DEFAULT_NAME, Class 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", + "/xl/worksheets/sheet#.xml", + null + ); + public static final XSSFRelation SHARED_STRINGS = new XSSFRelation( + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", + "/xl/sharedStrings.xml", + SharedStringsTable.class + ); + public static final XSSFRelation STYLES = new XSSFRelation( + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", + "/xl/styles.xml", + StylesTable.class + ); + public static final XSSFRelation DRAWINGS = new XSSFRelation( + "application/vnd.openxmlformats-officedocument.drawingml.chart+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", + "/xl/drawings/drawing#.xml", + null + ); + public static final XSSFRelation IMAGES = new XSSFRelation( + null, // TODO + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/xl/image#.xml", + null + ); private CTWorkbook workbook; @@ -107,20 +142,24 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { Iterator it; // Load shared strings - prc = getCorePart().getRelationshipsByType(SHARED_STRINGS_RELATIONSHIP); + 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_RELATIONSHIP); + 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"); } // Load individual sheets @@ -276,10 +315,10 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { if (sheetPart == null) { continue; } - PackageRelationshipCollection prc = sheetPart.getRelationshipsByType(DRAWING_RELATIONSHIP); + PackageRelationshipCollection prc = sheetPart.getRelationshipsByType(DRAWINGS.getRelation()); for (PackageRelationship rel : prc) { PackagePart drawingPart = getTargetPart(rel); - PackageRelationshipCollection prc2 = drawingPart.getRelationshipsByType(IMAGE_RELATIONSHIP); + PackageRelationshipCollection prc2 = drawingPart.getRelationshipsByType(IMAGES.getRelation()); for (PackageRelationship rel2 : prc2) { PackagePart imagePart = getTargetPart(rel2); XSSFPictureData pd = new XSSFPictureData(imagePart); @@ -519,8 +558,8 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { for (int i = 0 ; i < this.getNumberOfSheets() ; ++i) { XSSFSheet sheet = (XSSFSheet) this.getSheetAt(i); PackagePartName partName = PackagingURIHelper.createPartName("/xl/worksheets/sheet" + i + ".xml"); - corePart.addRelationship(partName, TargetMode.INTERNAL, WORKSHEET_RELATIONSHIP, "rSheet" + 1); - PackagePart part = pkg.createPart(partName, WORKSHEET_TYPE); + corePart.addRelationship(partName, TargetMode.INTERNAL, WORKSHEET.getRelation(), "rSheet" + 1); + PackagePart part = pkg.createPart(partName, WORKSHEET.getContentType()); // XXX This should not be needed, but apparently the setSaveOuter call above does not work in XMLBeans 2.2 xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); @@ -530,11 +569,28 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { out.close(); } - // TODO - shared strings source - // TODO - styles source - + // 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(); + } + 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(); + } + + // All done pkg.close(); - } catch (InvalidFormatException e) { // TODO: replace with more meaningful exception throw new RuntimeException(e); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index eea58b89e..89a066107 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -145,6 +145,33 @@ public class TestXSSFWorkbook extends TestCase { assertNotNull(workbook.getStylesSource()); } + public void testLoadSave() throws Exception { + File xml = new File( + System.getProperty("HSSF.testdata.path") + + File.separator + "Formatting.xlsx" + ); + assertTrue(xml.exists()); + + XSSFWorkbook workbook = new XSSFWorkbook(xml.toString()); + assertEquals(3, workbook.getNumberOfSheets()); + assertEquals("dd/mm/yyyy", workbook.getSheetAt(0).getRow(1).getCell(0).getRichStringCellValue().getString()); + assertNotNull(workbook.getSharedStringSource()); + assertNotNull(workbook.getStylesSource()); + + // Write out, and check + File tmpFile = File.createTempFile("poi-tmp", ".xlsx"); + workbook.write(new FileOutputStream(tmpFile)); + + // Load up again, check all still there + XSSFWorkbook wb2 = new XSSFWorkbook(tmpFile.toString()); + assertEquals(3, wb2.getNumberOfSheets()); + + // TODO - fix these! + assertEquals("dd/mm/yyyy", wb2.getSheetAt(0).getRow(1).getCell(0).getRichStringCellValue().getString()); + assertNotNull(wb2.getSharedStringSource()); + assertNotNull(wb2.getStylesSource()); + } + public void testStyles() throws Exception { File xml = new File( System.getProperty("HSSF.testdata.path") +