diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java index 6fccf1cb5..0aeba7450 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java @@ -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; diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java index 3657c1fa6..c73d4ed6f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java @@ -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 relations = doc.getRelations(); + int i = 1; + for (Iterator 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; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java index 7131cceb8..e0b4ed9a2 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java @@ -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; /** @@ -28,5 +32,9 @@ public class XWPFFooter extends XWPFHeaderFooter { public XWPFFooter(CTHdrFtr hdrFtr) { super(hdrFtr); } + + public XWPFFooter(PackagePart part, PackageRelationship rel) throws IOException { + super(part, rel); + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java index 971b403cb..69dc84dec 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java @@ -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; /** @@ -28,5 +32,9 @@ public class XWPFHeader extends XWPFHeaderFooter { public XWPFHeader(CTHdrFtr hdrFtr) { super(hdrFtr); } + + public XWPFHeader(PackagePart part, PackageRelationship rel) throws IOException { + super(part, rel); + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java index 3c84bf228..1481697d0 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java @@ -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) { @@ -30,6 +35,10 @@ public abstract class XWPFHeaderFooter { protected XWPFHeaderFooter() { headerFooter = CTHdrFtr.Factory.newInstance(); } + + public XWPFHeaderFooter(PackagePart part, PackageRelationship rel) throws IOException { + super(part, rel); + } public CTHdrFtr _getHdrFtr() { return headerFooter; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java index d28915e35..13c12c61b 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java @@ -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, diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java new file mode 100644 index 000000000..61081062e --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java @@ -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()); + } + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/headerFooter.docx b/src/scratchpad/testcases/org/apache/poi/hwpf/data/headerFooter.docx new file mode 100644 index 000000000..87a86c302 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hwpf/data/headerFooter.docx differ