improved API for OOXML custom properties

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@821496 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-10-04 10:00:52 +00:00
parent a6ced5bc25
commit bee594dc5e
3 changed files with 153 additions and 74 deletions

View File

@ -47,23 +47,14 @@ public class WorkbookProperties {
ext.getUnderlyingProperties().setTemplate("XSSF"); ext.getUnderlyingProperties().setTemplate("XSSF");
/** /**
* Custom properties enable users to define custom metadata properties * 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:
*
* <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="Editor">
* <vt:lpwstr>John Smith</vt:lpwstr>
* </property>
*/ */
POIXMLProperties.CustomProperties cust = props.getCustomProperties(); POIXMLProperties.CustomProperties cust = props.getCustomProperties();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty cust.addProperty("Author", "John Smith");
property = cust.getUnderlyingProperties().addNewProperty(); cust.addProperty("Year", 2009);
cust.addProperty("Price", 45.50);
property.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"); cust.addProperty("Available", true);
property.setPid(2);
property.setName("Editor");
property.setLpwstr("John Smith");
FileOutputStream out = new FileOutputStream("workbook.xlsx"); FileOutputStream out = new FileOutputStream("workbook.xlsx");
workbook.write(out); workbook.write(out);

View File

@ -34,6 +34,7 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable; import org.apache.poi.openxml4j.util.Nullable;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
/** /**
* Wrapper around the two different kinds of OOXML properties * Wrapper around the two different kinds of OOXML properties
@ -150,8 +151,14 @@ public class POIXMLProperties {
out.close(); out.close();
} }
if(custPart != null){ if(custPart != null){
XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
Map<String, String> map = new HashMap<String, String>();
map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt");
xmlOptions.setSaveSuggestedPrefixes(map);
OutputStream out = custPart.getOutputStream(); OutputStream out = custPart.getOutputStream();
cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS); cust.props.save(out, xmlOptions);
out.close(); out.close();
} }
} }
@ -274,6 +281,12 @@ public class POIXMLProperties {
* Custom document properties * Custom document properties
*/ */
public class CustomProperties { public class CustomProperties {
/**
* 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 org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) { private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) {
this.props = props; this.props = props;
@ -282,5 +295,91 @@ public class POIXMLProperties {
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() { public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() {
return props.getProperties(); 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;
}
} }
} }

View File

@ -27,6 +27,7 @@ import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties;
/** /**
* Test setting extended and custom OOXML properties * Test setting extended and custom OOXML properties
@ -85,66 +86,54 @@ public final class TestPOIXMLProperties extends TestCase {
} }
public void testWorkbookCustomProperties() { /**
XSSFWorkbook workbook = new XSSFWorkbook(); * Test usermodel API for setting custom properties
POIXMLProperties props = workbook.getProperties(); */
assertNotNull(props); public void testCustomProperties() {
POIXMLDocument wb = new XSSFWorkbook();
org.apache.poi.POIXMLProperties.CustomProperties properties = POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties();
props.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 wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb);
ctProps = properties.getUnderlyingProperties(); 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 p = ctProps.getPropertyArray(1);
property = ctProps.addNewProperty(); assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-2", p.getName());
assertEquals(1974, p.getI4());
String fmtid = assertEquals(3, p.getPid());
"{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}";
int pId = 1;
String name = "testProperty";
String stringValue = "testValue";
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());
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());
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());
} }
public void testDocumentProperties() { public void testDocumentProperties() {