diff options
Diffstat (limited to 'src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java')
-rw-r--r-- | src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java new file mode 100644 index 0000000000..f8ff5c84b0 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -0,0 +1,322 @@ +/* ==================================================================== + 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.IOException; +import java.io.OutputStream; +import java.util.*; + +import org.apache.poi.POIXMLDocument; +import org.apache.poi.POIXMLException; +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.util.PackageHelper; +import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.openxml4j.exceptions.InvalidFormatException; +import org.openxml4j.exceptions.OpenXML4JException; +import org.openxml4j.opc.*; +import org.openxml4j.opc.Package; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CommentsDocument; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.DocumentDocument; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; + +import javax.xml.namespace.QName; + +/** + * Experimental class to do low level processing + * of docx files. + * + * If you are using these low level classes, then you + * will almost certainly need to refer to the OOXML + * specifications from + * http://www.ecma-international.org/publications/standards/Ecma-376.htm + * + * WARNING - APIs expected to change rapidly + */ +public class XWPFDocument extends POIXMLDocument { + + private CTDocument1 ctDocument; + protected List<XWPFComment> comments; + protected List<XWPFHyperlink> hyperlinks; + protected List<XWPFParagraph> paragraphs; + protected List<XWPFTable> tables; + + /** Handles the joy of different headers/footers for different pages */ + private XWPFHeaderFooterPolicy headerFooterPolicy; + + public XWPFDocument(Package pkg) throws IOException { + super(ensureWriteAccess(pkg)); + + //build a tree of POIXMLDocumentParts, this document being the root + try { + read(XWPFFactory.getInstance()); + } catch (OpenXML4JException e){ + throw new POIXMLException(e); + } + onDocumentRead(); + } + + public XWPFDocument(){ + super(newPackage()); + onDocumentCreate(); + } + + @Override + protected void onDocumentRead() throws IOException { + hyperlinks = new ArrayList<XWPFHyperlink>(); + comments = new ArrayList<XWPFComment>(); + paragraphs = new ArrayList<XWPFParagraph>(); + tables= new ArrayList<XWPFTable>(); + + try { + DocumentDocument doc = DocumentDocument.Factory.parse(getPackagePart().getInputStream()); + ctDocument = doc.getDocument(); + + CTBody body = ctDocument.getBody(); + + // filling paragraph list + for (CTP p : body.getPArray()) { + paragraphs.add(new XWPFParagraph(p, this)); + } + + // Get any tables + for(CTTbl table : body.getTblArray()) { + tables.add(new XWPFTable(table)); + } + + // Sort out headers and footers + headerFooterPolicy = new XWPFHeaderFooterPolicy(this); + + for(POIXMLDocumentPart p : getRelations()){ + String relation = p.getPackageRelationship().getRelationshipType(); + if(relation.equals(XWPFRelation.COMMENT_RELATION_TYPE)){ + CommentsDocument cmntdoc = CommentsDocument.Factory.parse(p.getPackagePart().getInputStream()); + for(CTComment ctcomment : cmntdoc.getComments().getCommentArray()) { + comments.add(new XWPFComment(ctcomment)); + } + } + } + + initHyperlinks(); + + } catch (XmlException e) { + throw new POIXMLException(e); + } + } + + private void initHyperlinks(){ + // Get the hyperlinks + // TODO: make me optional/separated in private function + try { + Iterator <PackageRelationship> relIter = + getPackagePart().getRelationshipsByType(XWPFRelation.HYPERLINK_RELATION_TYPE).iterator(); + while(relIter.hasNext()) { + PackageRelationship rel = relIter.next(); + hyperlinks.add(new XWPFHyperlink(rel.getId(), rel.getTargetURI().toString())); + } + } catch (InvalidFormatException e){ + throw new POIXMLException(e); + } + } + + /** + * Create a new SpreadsheetML package and setup the default minimal content + */ + protected static Package newPackage() { + try { + Package pkg = Package.create(PackageHelper.createTempFile()); + // Main part + PackagePartName corePartName = PackagingURIHelper.createPartName(XWPFRelation.DOCUMENT.getDefaultFileName()); + // Create main part relationship + pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT); + // Create main document part + pkg.createPart(corePartName, XWPFRelation.DOCUMENT.getContentType()); + + pkg.getPackageProperties().setCreatorProperty("Apache POI"); + + return pkg; + } catch (Exception e){ + throw new POIXMLException(e); + } + } + + /** + * Create a new CTWorkbook with all values set to default + */ + protected void onDocumentCreate() { + hyperlinks = new ArrayList<XWPFHyperlink>(); + comments = new ArrayList<XWPFComment>(); + paragraphs = new ArrayList<XWPFParagraph>(); + tables= new ArrayList<XWPFTable>(); + + ctDocument = CTDocument1.Factory.newInstance(); + ctDocument.addNewBody(); + } + + /** + * Returns the low level document base object + */ + public CTDocument1 getDocument() { + return ctDocument; + } + + public Iterator<XWPFParagraph> getParagraphsIterator() { + return paragraphs.iterator(); + } + public XWPFParagraph[] getParagraphs() { + return paragraphs.toArray( + new XWPFParagraph[paragraphs.size()] + ); + } + + public Iterator<XWPFTable> getTablesIterator() + { + return tables.iterator(); + } + + public XWPFHyperlink getHyperlinkByID(String id) { + Iterator<XWPFHyperlink> iter = hyperlinks.iterator(); + while(iter.hasNext()) + { + XWPFHyperlink link = iter.next(); + if(link.getId().equals(id)) + return link; + } + + return null; + } + public XWPFHyperlink[] getHyperlinks() { + return hyperlinks.toArray( + new XWPFHyperlink[hyperlinks.size()] + ); + } + + public XWPFComment getCommentByID(String id) { + Iterator<XWPFComment> iter = comments.iterator(); + while(iter.hasNext()) + { + XWPFComment comment = iter.next(); + if(comment.getId().equals(id)) + return comment; + } + + return null; + } + public XWPFComment[] getComments() { + return comments.toArray( + new XWPFComment[comments.size()] + ); + } + + /** + * Get the document part that's defined as the + * given relationship of the core document. + */ + public PackagePart getPartById(String id) { + try { + return getTargetPart( + getCorePart().getRelationship(id) + ); + } catch(InvalidFormatException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Returns the policy on headers and footers, which + * also provides a way to get at them. + */ + public XWPFHeaderFooterPolicy getHeaderFooterPolicy() { + return headerFooterPolicy; + } + + /** + * Returns the styles object used + */ + public CTStyles getStyle() throws XmlException, IOException { + PackagePart[] parts; + try { + parts = getRelatedByType(XWPFRelation.STYLES_RELATION_TYPE); + } catch(InvalidFormatException e) { + throw new IllegalStateException(e); + } + if(parts.length != 1) { + throw new IllegalStateException("Expecting one Styles document part, but found " + parts.length); + } + + StylesDocument sd = + StylesDocument.Factory.parse(parts[0].getInputStream()); + return sd.getStyles(); + } + + /** + * Get the document's embedded files. + */ + public List<PackagePart> getAllEmbedds() throws OpenXML4JException { + List<PackagePart> embedds = new LinkedList<PackagePart>(); + + // Get the embeddings for the workbook + for(PackageRelationship rel : getPackagePart().getRelationshipsByType(OLE_OBJECT_REL_TYPE)) + embedds.add(getTargetPart(rel)); + + for(PackageRelationship rel : getPackagePart().getRelationshipsByType(PACK_OBJECT_REL_TYPE)) + embedds.add(getTargetPart(rel)); + + return embedds; + } + + @Override + protected void commit() throws IOException { + + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDocument1.type.getName().getNamespaceURI(), "document")); + 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); + + PackagePart part = getPackagePart(); + OutputStream out = part.getOutputStream(); + ctDocument.save(out, xmlOptions); + out.close(); + } + + /** + * Appends a new paragraph to this document + * + * @return a new paragraph + */ + public XWPFParagraph createParagraph(){ + return new XWPFParagraph(ctDocument.getBody().addNewP(), this); + } + +} + |