createHeader/Footer methods + tests

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@805422 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Paolo Mottadelli 2009-08-18 14:08:09 +00:00
parent c83d6bfa24
commit 05c8f883e4
8 changed files with 270 additions and 25 deletions

View File

@ -190,11 +190,11 @@ public class POIXMLDocumentPart {
* @param factory the factory that will create an instance of the requested relation
* @return the created child POIXMLDocumentPart
*/
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){
public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){
return createRelationship(descriptor, factory, -1, false);
}
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){
public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){
return createRelationship(descriptor, factory, idx, false);
}
@ -209,11 +209,9 @@ public class POIXMLDocumentPart {
*/
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){
try {
PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx));
PackageRelationship rel = null;
if(!noRelation) rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation());
PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType());
POIXMLDocumentPart doc = factory.newDocumentPart(descriptor);
doc.packageRel = rel;

View File

@ -17,17 +17,31 @@
package org.apache.poi.xwpf.model;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFactory;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFHeaderFooter;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.xmlbeans.XmlException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.HdrDocument;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.Enum;
/**
* A .docx file can have no headers/footers, the same header/footer
@ -37,6 +51,12 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;
* the right headers and footers for the document.
*/
public class XWPFHeaderFooterPolicy {
public static final Enum DEFAULT = STHdrFtr.DEFAULT;
public static final Enum EVEN = STHdrFtr.EVEN;
public static final Enum FIRST = STHdrFtr.FIRST;
private XWPFDocument doc;
private XWPFHeader firstPageHeader;
private XWPFFooter firstPageFooter;
@ -57,23 +77,19 @@ public class XWPFHeaderFooterPolicy {
// For now, we don't care about different ranges, as it
// doesn't seem that .docx properly supports that
// feature of the file format yet
this.doc = doc;
CTSectPr sectPr = doc.getDocument().getBody().getSectPr();
for(int i=0; i<sectPr.sizeOfHeaderReferenceArray(); i++) {
// Get the header
CTHdrFtrRef ref = sectPr.getHeaderReferenceArray(i);
PackagePart hdrPart = doc.getPartById(ref.getId());
XWPFHeader hdr = new XWPFHeader(
HdrDocument.Factory.parse(hdrPart.getInputStream()).getHdr()
);
HdrDocument hdrDoc = HdrDocument.Factory.parse(hdrPart.getInputStream());
CTHdrFtr hdrFtr = hdrDoc.getHdr();
XWPFHeader hdr = new XWPFHeader(hdrFtr);
// Assign it
if(ref.getType() == STHdrFtr.FIRST) {
firstPageHeader = hdr;
} else if(ref.getType() == STHdrFtr.EVEN) {
evenPageHeader = hdr;
} else {
defaultHeader = hdr;
}
Enum type = ref.getType();
assignHeader(hdr, type);
}
for(int i=0; i<sectPr.sizeOfFooterReferenceArray(); i++) {
// Get the footer
@ -84,17 +100,146 @@ public class XWPFHeaderFooterPolicy {
);
// Assign it
if(ref.getType() == STHdrFtr.FIRST) {
Enum type = ref.getType();
assignFooter(ftr, type);
}
}
private void assignFooter(XWPFFooter ftr, Enum type) {
if(type == STHdrFtr.FIRST) {
firstPageFooter = ftr;
} else if(ref.getType() == STHdrFtr.EVEN) {
} else if(type == STHdrFtr.EVEN) {
evenPageFooter = ftr;
} else {
defaultFooter = ftr;
}
}
private void assignHeader(XWPFHeader hdr, Enum type) {
if(type == STHdrFtr.FIRST) {
firstPageHeader = hdr;
} else if(type == STHdrFtr.EVEN) {
evenPageHeader = hdr;
} else {
defaultHeader = hdr;
}
}
public XWPFHeader createHeader(Enum type) throws IOException {
XWPFRelation relation = XWPFRelation.HEADER;
String pStyle = "Header";
int i = getRelationIndex(relation);
HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
XWPFHeader wrapper = (XWPFHeader)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
CTHdrFtr hdr = buildHdr(type, pStyle, wrapper);
OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
hdrDoc.setHdr(hdr);
XmlOptions xmlOptions = commit(wrapper);
assignHeader(wrapper, type);
hdrDoc.save(outputStream, xmlOptions);
outputStream.close();
return wrapper;
}
public XWPFFooter createFooter(Enum type) throws IOException {
XWPFRelation relation = XWPFRelation.FOOTER;
String pStyle = "Footer";
int i = getRelationIndex(relation);
FtrDocument ftrDoc = FtrDocument.Factory.newInstance();
XWPFFooter wrapper = (XWPFFooter)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
CTHdrFtr ftr = buildFtr(type, pStyle, wrapper);
OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
ftrDoc.setFtr(ftr);
XmlOptions xmlOptions = commit(wrapper);
assignFooter(wrapper, type);
ftrDoc.save(outputStream, xmlOptions);
outputStream.close();
return wrapper;
}
private int getRelationIndex(XWPFRelation relation) {
List<POIXMLDocumentPart> relations = doc.getRelations();
int i = 1;
for (Iterator<POIXMLDocumentPart> it = relations.iterator(); it.hasNext() ; ) {
POIXMLDocumentPart item = it.next();
if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) {
i++;
}
}
return i;
}
private CTHdrFtr buildFtr(Enum type, String pStyle, XWPFHeaderFooter wrapper) {
CTHdrFtr ftr = buildHdrFtr(pStyle);
setFooterReference(type, wrapper);
return ftr;
}
private CTHdrFtr buildHdr(Enum type, String pStyle, XWPFHeaderFooter wrapper) {
CTHdrFtr hdr = buildHdrFtr(pStyle);
setHeaderReference(type, wrapper);
return hdr;
}
private CTHdrFtr buildHdrFtr(String pStyle) {
CTHdrFtr ftr = CTHdrFtr.Factory.newInstance();
CTP p = ftr.addNewP();
byte[] rsidr = doc.getDocument().getBody().getPArray()[0].getRsidR();
byte[] rsidrdefault = doc.getDocument().getBody().getPArray()[0].getRsidRDefault();
p.setRsidP(rsidr);
p.setRsidRDefault(rsidrdefault);
CTPPr pPr = p.addNewPPr();
pPr.addNewPStyle().setVal(pStyle);
return ftr;
}
private void setFooterReference(Enum type, XWPFHeaderFooter wrapper) {
CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewFooterReference();
ref.setType(type);
ref.setId(wrapper.getPackageRelationship().getId());
}
private void setHeaderReference(Enum type, XWPFHeaderFooter wrapper) {
CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewHeaderReference();
ref.setType(type);
ref.setId(wrapper.getPackageRelationship().getId());
}
private XmlOptions commit(XWPFHeaderFooter wrapper) {
XmlOptions xmlOptions = new XmlOptions(wrapper.DEFAULT_XML_OPTIONS);
Map map = new HashMap();
map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m");
map.put("urn:schemas-microsoft-com:office:office", "o");
map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
map.put("urn:schemas-microsoft-com:vml", "v");
map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve");
map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w");
map.put("urn:schemas-microsoft-com:office:word", "w10");
map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne");
map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp");
xmlOptions.setSaveSuggestedPrefixes(map);
return xmlOptions;
}
public XWPFHeader getFirstPageHeader() {
return firstPageHeader;
}

View File

@ -16,6 +16,10 @@
==================================================================== */
package org.apache.poi.xwpf.usermodel;
import java.io.IOException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
/**
@ -29,4 +33,8 @@ public class XWPFFooter extends XWPFHeaderFooter {
super(hdrFtr);
}
public XWPFFooter(PackagePart part, PackageRelationship rel) throws IOException {
super(part, rel);
}
}

View File

@ -16,6 +16,10 @@
==================================================================== */
package org.apache.poi.xwpf.usermodel;
import java.io.IOException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
/**
@ -29,4 +33,8 @@ public class XWPFHeader extends XWPFHeaderFooter {
super(hdrFtr);
}
public XWPFHeader(PackagePart part, PackageRelationship rel) throws IOException {
super(part, rel);
}
}

View File

@ -16,12 +16,17 @@
==================================================================== */
package org.apache.poi.xwpf.usermodel;
import java.io.IOException;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
/**
* Parent of XWPF headers and footers
*/
public abstract class XWPFHeaderFooter {
public abstract class XWPFHeaderFooter extends POIXMLDocumentPart{
protected CTHdrFtr headerFooter;
protected XWPFHeaderFooter(CTHdrFtr hdrFtr) {
@ -31,6 +36,10 @@ public abstract class XWPFHeaderFooter {
headerFooter = CTHdrFtr.Factory.newInstance();
}
public XWPFHeaderFooter(PackagePart part, PackageRelationship rel) throws IOException {
super(part, rel);
}
public CTHdrFtr _getHdrFtr() {
return headerFooter;
}

View File

@ -86,13 +86,13 @@ public final class XWPFRelation extends POIXMLRelation {
"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
"/word/header#.xml",
null
XWPFHeader.class
);
public static final XWPFRelation FOOTER = new XWPFRelation(
"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
"/word/footer#.xml",
null
XWPFFooter.class
);
public static final XWPFRelation HYPERLINK = new XWPFRelation(
null,

View File

@ -0,0 +1,77 @@
/* ====================================================================
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.xwpf.usermodel;
import java.io.File;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
public class TestXWPFHeader extends TestCase {
public void testSimpleHeader() throws IOException {
File sampleFile = new File(
System.getProperty("HWPF.testdata.path") +
File.separator + "headerFooter.docx"
);
assertTrue(sampleFile.exists());
XWPFDocument sampleDoc;
sampleDoc = new XWPFDocument(
POIXMLDocument.openPackage(sampleFile.toString())
);
XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy();
XWPFHeader header = policy.getDefaultHeader();
XWPFFooter footer = policy.getDefaultFooter();
assertNotNull(header);
assertNotNull(footer);
// TODO verify if the following is correct
assertNull(header.toString());
}
public void testSetHeader() throws IOException {
File sampleFile = new File(
System.getProperty("HWPF.testdata.path") +
File.separator + "sampleDoc.docx"
);
assertTrue(sampleFile.exists());
XWPFDocument sampleDoc;
sampleDoc = new XWPFDocument(
POIXMLDocument.openPackage(sampleFile.toString())
);
// no header is set (yet)
XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy();
assertNull(policy.getDefaultHeader());
// set a default header and test it is not null
policy.createHeader(policy.DEFAULT);
policy.createHeader(policy.FIRST);
policy.createFooter(policy.DEFAULT);
assertNotNull(policy.getDefaultHeader());
assertNotNull(policy.getFirstPageHeader());
assertNotNull(policy.getDefaultFooter());
}
}