Fix for saving custom and extended OOXML properties

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@795587 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-07-19 18:26:36 +00:00
parent bf76476b0e
commit 9196f6e6dd
5 changed files with 291 additions and 26 deletions

View File

@ -33,7 +33,8 @@
<changes>
<release version="3.5-beta7" date="2009-??-??">
<action dev="POI-DEVELOPERS" type="fix">47535 - fixed WordExtractor to tolerate files with empty footnote block</action>
<action dev="POI-DEVELOPERS" type="fix">47540 - Fix for saving custom and extended OOXML properties</action>
<action dev="POI-DEVELOPERS" type="fix">47535 - Fixed WordExtractor to tolerate files with empty footnote block</action>
<action dev="POI-DEVELOPERS" type="fix">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action>
<action dev="POI-DEVELOPERS" type="add">45556 - Support for extraction of footnotes from docx files</action>
<action dev="POI-DEVELOPERS" type="add">45555 - Support for extraction of endnotes from docx files</action>

View File

@ -0,0 +1,75 @@
/* ====================================================================
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.usermodel.examples;
import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.POIXMLProperties;
/**
* How to set extended and custom properties
*
* @author Yegor Kozlov
*/
public class WorkbookProperties {
public static void main(String[]args) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
workbook.createSheet("Workbook Properties");
POIXMLProperties props = workbook.getProperties();
/**
* Extended properties are a predefined set of metadata properties
* that are specifically applicable to Office Open XML documents.
* Extended properties consist of 24 simple properties and 3 complex properties stored in the
* part targeted by the relationship of type
*/
POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties();
ext.getUnderlyingProperties().setCompany("Apache Software Foundation");
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:
*
* <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="Editor">
* <vt:lpwstr>John Smith</vt:lpwstr>
* </property>
*/
POIXMLProperties.CustomProperties cust = props.getCustomProperties();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
property = cust.getUnderlyingProperties().addNewProperty();
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();
}
}

View File

@ -157,9 +157,13 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{
* Get the document properties. This gives you access to the
* core ooxml properties, and the extended ooxml properties.
*/
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException {
public POIXMLProperties getProperties() {
if(properties == null) {
properties = new POIXMLProperties(pkg);
try {
properties = new POIXMLProperties(pkg);
} catch (Exception e){
throw new POIXMLException(e);
}
}
return properties;
}
@ -197,6 +201,9 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{
//force all children to commit their changes into the underlying OOXML Package
onSave();
//save extended and custom properties
getProperties().commit();
getPackage().save(stream);
}

View File

@ -17,12 +17,17 @@
package org.apache.poi;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.HashMap;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument;
/**
* Wrapper around the two different kinds of OOXML properties
@ -33,8 +38,22 @@ public class POIXMLProperties {
private CoreProperties core;
private ExtendedProperties ext;
private CustomProperties cust;
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
private PackagePart extPart;
private PackagePart custPart;
private static final org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument NEW_EXT_INSTANCE;
private static final org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument NEW_CUST_INSTANCE;
static {
NEW_EXT_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance();
NEW_EXT_INSTANCE.addNewProperties();
NEW_CUST_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance();
NEW_CUST_INSTANCE.addNewProperties();
}
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
this.pkg = docPackage;
// Core properties
@ -44,24 +63,28 @@ public class POIXMLProperties {
PackageRelationshipCollection extRel =
pkg.getRelationshipsByType(POIXMLDocument.EXTENDED_PROPERTIES_REL_TYPE);
if(extRel.size() == 1) {
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
pkg.getPart( extRel.getRelationship(0) ).getInputStream()
extPart = pkg.getPart( extRel.getRelationship(0));
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
extPart.getInputStream()
);
ext = new ExtendedProperties(props);
} else {
ext = new ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance());
}
extPart = null;
ext = new ExtendedProperties((org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument)NEW_EXT_INSTANCE.copy());
}
// Custom properties
PackageRelationshipCollection custRel =
pkg.getRelationshipsByType(POIXMLDocument.CUSTOM_PROPERTIES_REL_TYPE);
if(custRel.size() == 1) {
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
pkg.getPart( custRel.getRelationship(0) ).getInputStream()
custPart = pkg.getPart( custRel.getRelationship(0));
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
custPart.getInputStream()
);
cust = new CustomProperties(props);
} else {
cust = new CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance());
custPart = null;
cust = new CustomProperties((org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument)NEW_CUST_INSTANCE.copy());
}
}
@ -87,11 +110,44 @@ public class POIXMLProperties {
}
/**
* Writes out the ooxml properties into the supplied,
* new Package
* Commit changes to the underlying OPC package
*/
public void write(OPCPackage pkg) {
// TODO
public void commit() throws IOException{
if(extPart == null && !NEW_EXT_INSTANCE.toString().equals(ext.props.toString())){
try {
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/app.xml");
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
extPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.extended-properties+xml");
} catch (InvalidFormatException e){
throw new POIXMLException(e);
}
}
if(custPart == null && !NEW_CUST_INSTANCE.toString().equals(cust.props.toString())){
try {
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/custom.xml");
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
custPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.custom-properties+xml");
} catch (InvalidFormatException e){
throw new POIXMLException(e);
}
}
if(extPart != 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 = extPart.getOutputStream();
ext.props.save(out, xmlOptions);
out.close();
}
if(custPart != null){
OutputStream out = custPart.getOutputStream();
cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
out.close();
}
}
/**
@ -122,10 +178,6 @@ public class POIXMLProperties {
private org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props;
private ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props) {
this.props = props;
if(props.getProperties() == null) {
props.addNewProperties();
}
}
public org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties getUnderlyingProperties() {
@ -140,10 +192,6 @@ public class POIXMLProperties {
private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) {
this.props = props;
if(props.getProperties() == null) {
props.addNewProperties();
}
}
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() {

View File

@ -0,0 +1,134 @@
/* ====================================================================
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;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.XSSFTestDataSamples;
import junit.framework.TestCase;
/**
* Test setting extended and custom OOXML properties
*/
public class TestPOIXMLProperties extends TestCase {
public void testWorkbookExtendedProperties() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties();
assertNotNull(props);
org.apache.poi.POIXMLProperties.ExtendedProperties properties =
props.getExtendedProperties();
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
ctProps = properties.getUnderlyingProperties();
String appVersion = "3.5 beta";
String application = "POI";
ctProps.setApplication(application);
ctProps.setAppVersion(appVersion);
ctProps = null;
properties = null;
props = null;
XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook);
assertTrue(workbook != newWorkbook);
POIXMLProperties newProps = newWorkbook.getProperties();
assertNotNull(newProps);
org.apache.poi.POIXMLProperties.ExtendedProperties newProperties =
newProps.getExtendedProperties();
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
newCtProps = newProperties.getUnderlyingProperties();
assertEquals(application, newCtProps.getApplication());
assertEquals(appVersion, newCtProps.getAppVersion());
}
public void testWorkbookCustomProperties() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties();
assertNotNull(props);
org.apache.poi.POIXMLProperties.CustomProperties properties =
props.getCustomProperties();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
ctProps = properties.getUnderlyingProperties();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
property = ctProps.addNewProperty();
String fmtid =
"{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());
}
}