From bee594dc5ee9eebe6cb5445b3af7a01d7e37d19f Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sun, 4 Oct 2009 10:00:52 +0000 Subject: [PATCH] improved API for OOXML custom properties git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@821496 13f79535-47bb-0310-9956-ffa450edef68 --- .../examples/WorkbookProperties.java | 19 +--- .../java/org/apache/poi/POIXMLProperties.java | 107 +++++++++++++++++- .../org/apache/poi/TestPOIXMLProperties.java | 101 ++++++++--------- 3 files changed, 153 insertions(+), 74 deletions(-) diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java index 0e00c7d94..3a8fd56d0 100755 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/WorkbookProperties.java @@ -47,24 +47,15 @@ public class WorkbookProperties { ext.getUnderlyingProperties().setTemplate("XSSF"); /** - * Custom properties enable users to define custom metadata properties - * through a set of well-defined data types. For example, a custom - * OLE Editor property of type string can be defined as follows: - * - * - * John Smith - * + * Custom properties enable users to define custom metadata properties. */ POIXMLProperties.CustomProperties cust = props.getCustomProperties(); - org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty - property = cust.getUnderlyingProperties().addNewProperty(); + cust.addProperty("Author", "John Smith"); + cust.addProperty("Year", 2009); + cust.addProperty("Price", 45.50); + cust.addProperty("Available", true); - property.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"); - property.setPid(2); - property.setName("Editor"); - property.setLpwstr("John Smith"); - FileOutputStream out = new FileOutputStream("workbook.xlsx"); workbook.write(out); out.close(); diff --git a/src/ooxml/java/org/apache/poi/POIXMLProperties.java b/src/ooxml/java/org/apache/poi/POIXMLProperties.java index 1ccf73674..c62b57db3 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLProperties.java +++ b/src/ooxml/java/org/apache/poi/POIXMLProperties.java @@ -34,6 +34,7 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.util.Nullable; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; /** * Wrapper around the two different kinds of OOXML properties @@ -150,8 +151,14 @@ public class POIXMLProperties { out.close(); } if(custPart != null){ + XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS); + + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); + xmlOptions.setSaveSuggestedPrefixes(map); + OutputStream out = custPart.getOutputStream(); - cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS); + cust.props.save(out, xmlOptions); out.close(); } } @@ -271,10 +278,16 @@ public class POIXMLProperties { } /** - * Custom document properties + * Custom document properties */ public class CustomProperties { - private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props; + /** + * Each custom property element contains an fmtid attribute + * with the same GUID value ({D5CDD505-2E9C-101B-9397-08002B2CF9AE}). + */ + public static final String FORMAT_ID = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"; + + private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props; private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) { this.props = props; } @@ -282,5 +295,91 @@ public class POIXMLProperties { public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() { return props.getProperties(); } - } + + /** + * Add a new property + * + * @param name the property name + * @throws IllegalArgumentException if a property with this name already exists + */ + private CTProperty add(String name) { + if(contains(name)) { + throw new IllegalArgumentException("A property with this name " + + "already exists in the custom properties"); + } + + CTProperty p = props.getProperties().addNewProperty(); + int pid = nextPid(); + p.setPid(pid); + p.setFmtid(FORMAT_ID); + p.setName(name); + return p; + } + + /** + * Add a new string property + * + * @throws IllegalArgumentException if a property with this name already exists + */ + public void addProperty(String name, String value){ + CTProperty p = add(name); + p.setLpwstr(value); + } + + /** + * Add a new double property + * + * @throws IllegalArgumentException if a property with this name already exists + */ + public void addProperty(String name, double value){ + CTProperty p = add(name); + p.setR8(value); + } + + /** + * Add a new integer property + * + * @throws IllegalArgumentException if a property with this name already exists + */ + public void addProperty(String name, int value){ + CTProperty p = add(name); + p.setI4(value); + } + + /** + * Add a new boolean property + * + * @throws IllegalArgumentException if a property with this name already exists + */ + public void addProperty(String name, boolean value){ + CTProperty p = add(name); + p.setBool(value); + } + + /** + * Generate next id that uniquely relates a custom property + * + * @return next property id starting with 2 + */ + protected int nextPid(){ + int propid = 1; + for(CTProperty p : props.getProperties().getPropertyArray()){ + if(p.getPid() > propid) propid = p.getPid(); + } + return propid + 1; + } + + /** + * Check if a property with this name already exists in the collection of custom properties + * + * @param name the name to check + * @return whether a property with the given name exists in the custom properties + */ + public boolean contains(String name){ + for(CTProperty p : props.getProperties().getPropertyArray()){ + if(p.getName().equals(name)) return true; + } + return false; + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java index ba9cfe92a..1aac08740 100644 --- a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java +++ b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java @@ -27,6 +27,7 @@ import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties; /** * Test setting extended and custom OOXML properties @@ -85,69 +86,57 @@ public final class TestPOIXMLProperties extends TestCase { } - public void testWorkbookCustomProperties() { - XSSFWorkbook workbook = new XSSFWorkbook(); - POIXMLProperties props = workbook.getProperties(); - assertNotNull(props); + /** + * Test usermodel API for setting custom properties + */ + public void testCustomProperties() { + POIXMLDocument wb = new XSSFWorkbook(); - org.apache.poi.POIXMLProperties.CustomProperties properties = - props.getCustomProperties(); + POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties(); + customProps.addProperty("test-1", "string val"); + customProps.addProperty("test-2", 1974); + customProps.addProperty("test-3", 36.6); + //adding a duplicate + try { + customProps.addProperty("test-3", 36.6); + fail("expected exception"); + } catch(IllegalArgumentException e){ + assertEquals("A property with this name already exists in the custom properties", e.getMessage()); + } + customProps.addProperty("test-4", true); - org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties - ctProps = properties.getUnderlyingProperties(); + wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb); + org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps = + wb.getProperties().getCustomProperties().getUnderlyingProperties(); + assertEquals(4, ctProps.sizeOfPropertyArray()); + org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p; + p = ctProps.getPropertyArray(0); + assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); + assertEquals("test-1", p.getName()); + assertEquals("string val", p.getLpwstr()); + assertEquals(2, p.getPid()); - org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty - property = ctProps.addNewProperty(); + p = ctProps.getPropertyArray(1); + assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); + assertEquals("test-2", p.getName()); + assertEquals(1974, p.getI4()); + assertEquals(3, p.getPid()); + p = ctProps.getPropertyArray(2); + assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); + assertEquals("test-3", p.getName()); + assertEquals(36.6, p.getR8()); + assertEquals(4, p.getPid()); - String fmtid = - "{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}"; - int pId = 1; - String name = "testProperty"; - String stringValue = "testValue"; + p = ctProps.getPropertyArray(3); + assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); + assertEquals("test-4", p.getName()); + assertEquals(true, p.getBool()); + assertEquals(5, p.getPid()); + } - - property.setFmtid(fmtid); - property.setPid(pId); - property.setName(name); - property.setBstr(stringValue); - - - property = null; - ctProps = null; - properties = null; - props = null; - - XSSFWorkbook newWorkbook = - XSSFTestDataSamples.writeOutAndReadBack(workbook); - - assertTrue(workbook != newWorkbook); - - - POIXMLProperties newProps = newWorkbook.getProperties(); - assertNotNull(newProps); - org.apache.poi.POIXMLProperties.CustomProperties newProperties = - newProps.getCustomProperties(); - - org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties - newCtProps = newProperties.getUnderlyingProperties(); - - assertEquals(1, newCtProps.getPropertyArray().length); - - - org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty - newpProperty = newCtProps.getPropertyArray()[0]; - - assertEquals(fmtid, newpProperty.getFmtid()); - assertEquals(pId, newpProperty.getPid()); - assertEquals(name, newpProperty.getName()); - assertEquals(stringValue, newpProperty.getBstr()); - - - } - - public void testDocumentProperties() { + public void testDocumentProperties() { String category = _coreProperties.getCategory(); assertEquals("test", category); String contentStatus = "Draft";