123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- /* ====================================================================
- 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.io.InputStream;
- import java.util.*;
-
- import org.apache.poi.POIXMLDocument;
- import org.apache.poi.POIXMLException;
- import org.apache.poi.POIXMLDocumentPart;
- import org.apache.poi.POIXMLProperties;
- 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.apache.poi.openxml4j.exceptions.InvalidFormatException;
- import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
- import org.apache.poi.openxml4j.opc.*;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
- 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;
- private XWPFSettings settings;
- protected List<XWPFComment> comments;
- protected List<XWPFHyperlink> hyperlinks;
- protected List<XWPFParagraph> paragraphs;
- protected List<XWPFTable> tables;
- protected Map<Integer, XWPFFootnote> footnotes;
- protected Map<Integer, XWPFFootnote> endnotes;
-
- /** Handles the joy of different headers/footers for different pages */
- private XWPFHeaderFooterPolicy headerFooterPolicy;
-
- public XWPFDocument(OPCPackage pkg) throws IOException {
- super(ensureWriteAccess(pkg));
-
- //build a tree of POIXMLDocumentParts, this document being the root
- load(XWPFFactory.getInstance());
- }
-
- public XWPFDocument(InputStream is) throws IOException {
- super(PackageHelper.open(is));
-
- //build a tree of POIXMLDocumentParts, this workbook being the root
- load(XWPFFactory.getInstance());
- }
-
- 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>();
- footnotes = new HashMap<Integer, XWPFFootnote>();
- endnotes = new HashMap<Integer, XWPFFootnote>();
-
- try {
- DocumentDocument doc = DocumentDocument.Factory.parse(getPackagePart().getInputStream());
- ctDocument = doc.getDocument();
-
- CTBody body = ctDocument.getBody();
-
- initFootnotes();
-
- // 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(this, table));
- }
-
- // Sort out headers and footers
- if (doc.getDocument().getBody().getSectPr() != null)
- headerFooterPolicy = new XWPFHeaderFooterPolicy(this);
-
- for(POIXMLDocumentPart p : getRelations()){
- String relation = p.getPackageRelationship().getRelationshipType();
- if(relation.equals(XWPFRelation.COMMENT.getRelation())){
- CommentsDocument cmntdoc = CommentsDocument.Factory.parse(p.getPackagePart().getInputStream());
- for(CTComment ctcomment : cmntdoc.getComments().getCommentArray()) {
- comments.add(new XWPFComment(ctcomment));
- }
- }
- else if(relation.equals(XWPFRelation.SETTINGS.getRelation())){
- settings = (XWPFSettings)p;
- }
- }
-
- 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.getRelation()).iterator();
- while(relIter.hasNext()) {
- PackageRelationship rel = relIter.next();
- hyperlinks.add(new XWPFHyperlink(rel.getId(), rel.getTargetURI().toString()));
- }
- } catch (InvalidFormatException e){
- throw new POIXMLException(e);
- }
- }
-
- private void initFootnotes() throws XmlException, IOException {
- for(POIXMLDocumentPart p : getRelations()){
- String relation = p.getPackageRelationship().getRelationshipType();
- if(relation.equals(XWPFRelation.FOOTNOTE.getRelation())){
- FootnotesDocument footnotesDocument = FootnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
-
- for(CTFtnEdn ctFtnEdn : footnotesDocument.getFootnotes().getFootnoteArray()) {
- footnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn));
- }
- } else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())){
- EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
-
- for(CTFtnEdn ctFtnEdn : endnotesDocument.getEndnotes().getEndnoteArray()) {
- endnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn));
- }
- }
- }
- }
-
- /**
- * Create a new SpreadsheetML package and setup the default minimal content
- */
- protected static OPCPackage newPackage() {
- try {
- OPCPackage pkg = OPCPackage.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(DOCUMENT_CREATOR);
-
- 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();
-
- settings = (XWPFSettings) createRelationship(XWPFRelation.SETTINGS, XWPFFactory.getInstance());
-
- POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties();
- expProps.getUnderlyingProperties().setApplication(DOCUMENT_CREATOR);
- }
-
- /**
- * 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 XWPFFootnote getFootnoteByID(int id) {
- return footnotes.get(id);
- }
-
- public XWPFFootnote getEndnoteByID(int id) {
- return endnotes.get(id);
- }
-
- public Collection<XWPFFootnote> getFootnotes() {
- return footnotes == null ? new ArrayList<XWPFFootnote>() : footnotes.values();
- }
-
- 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.getRelation());
- } 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<String, String> map = new HashMap<String, String>();
- 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);
- }
-
- /**
- * Create an empty table with one row and one column as default.
- *
- * @return a new table
- */
- public XWPFTable createTable(){
- return new XWPFTable(this, ctDocument.getBody().addNewTbl());
- }
-
- /**
- * Create an empty table with a number of rows and cols specified
- * @param rows
- * @param cols
- * @return table
- */
- public XWPFTable createTable(int rows, int cols) {
- return new XWPFTable(this, ctDocument.getBody().addNewTbl(), rows, cols);
- }
-
- public void createTOC() {
- CTSdtBlock block = this.getDocument().getBody().addNewSdt();
- TOC toc = new TOC(block);
- int i = 1;
- for (Iterator<XWPFParagraph> iterator = getParagraphsIterator() ; iterator.hasNext() ; ) {
- XWPFParagraph par = iterator.next();
- String parStyle = par.getStyle();
- if (parStyle != null && parStyle.substring(0, 7).equals("Heading")) {
- try {
- int level = Integer.valueOf(parStyle.substring("Heading".length()));
- toc.addRow(level, par.getText(), 1, "112723803");
- }
- catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- /**
- * Verifies that the documentProtection tag in settings.xml file <br/>
- * specifies that the protection is enforced (w:enforcement="1") <br/>
- * and that the kind of protection is readOnly (w:edit="readOnly")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="readOnly" w:enforcement="1"/>
- * </pre>
- *
- * @return true if documentProtection is enforced with option readOnly
- */
- public boolean isEnforcedReadonlyProtection() {
- return settings.isEnforcedWith(STDocProtect.READ_ONLY);
- }
-
- /**
- * Verifies that the documentProtection tag in settings.xml file <br/>
- * specifies that the protection is enforced (w:enforcement="1") <br/>
- * and that the kind of protection is forms (w:edit="forms")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="forms" w:enforcement="1"/>
- * </pre>
- *
- * @return true if documentProtection is enforced with option forms
- */
- public boolean isEnforcedFillingFormsProtection() {
- return settings.isEnforcedWith(STDocProtect.FORMS);
- }
-
- /**
- * Verifies that the documentProtection tag in settings.xml file <br/>
- * specifies that the protection is enforced (w:enforcement="1") <br/>
- * and that the kind of protection is comments (w:edit="comments")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="comments" w:enforcement="1"/>
- * </pre>
- *
- * @return true if documentProtection is enforced with option comments
- */
- public boolean isEnforcedCommentsProtection() {
- return settings.isEnforcedWith(STDocProtect.COMMENTS);
- }
-
- /**
- * Verifies that the documentProtection tag in settings.xml file <br/>
- * specifies that the protection is enforced (w:enforcement="1") <br/>
- * and that the kind of protection is trackedChanges (w:edit="trackedChanges")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="trackedChanges" w:enforcement="1"/>
- * </pre>
- *
- * @return true if documentProtection is enforced with option trackedChanges
- */
- public boolean isEnforcedTrackedChangesProtection() {
- return settings.isEnforcedWith(STDocProtect.TRACKED_CHANGES);
- }
-
- /**
- * Enforces the readOnly protection.<br/>
- * In the documentProtection tag inside settings.xml file, <br/>
- * it sets the value of enforcement to "1" (w:enforcement="1") <br/>
- * and the value of edit to readOnly (w:edit="readOnly")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="readOnly" w:enforcement="1"/>
- * </pre>
- */
- public void enforceReadonlyProtection() {
- settings.setEnforcementEditValue(STDocProtect.READ_ONLY);
- }
-
- /**
- * Enforce the Filling Forms protection.<br/>
- * In the documentProtection tag inside settings.xml file, <br/>
- * it sets the value of enforcement to "1" (w:enforcement="1") <br/>
- * and the value of edit to forms (w:edit="forms")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="forms" w:enforcement="1"/>
- * </pre>
- */
- public void enforceFillingFormsProtection() {
- settings.setEnforcementEditValue(STDocProtect.FORMS);
- }
-
- /**
- * Enforce the Comments protection.<br/>
- * In the documentProtection tag inside settings.xml file,<br/>
- * it sets the value of enforcement to "1" (w:enforcement="1") <br/>
- * and the value of edit to comments (w:edit="comments")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="comments" w:enforcement="1"/>
- * </pre>
- */
- public void enforceCommentsProtection() {
- settings.setEnforcementEditValue(STDocProtect.COMMENTS);
- }
-
- /**
- * Enforce the Tracked Changes protection.<br/>
- * In the documentProtection tag inside settings.xml file, <br/>
- * it sets the value of enforcement to "1" (w:enforcement="1") <br/>
- * and the value of edit to trackedChanges (w:edit="trackedChanges")<br/>
- * <br/>
- * sample snippet from settings.xml
- * <pre>
- * <w:settings ... >
- * <w:documentProtection w:edit="trackedChanges" w:enforcement="1"/>
- * </pre>
- */
- public void enforceTrackedChangesProtection() {
- settings.setEnforcementEditValue(STDocProtect.TRACKED_CHANGES);
- }
-
- /**
- * Remove protection enforcement.<br/>
- * In the documentProtection tag inside settings.xml file <br/>
- * it sets the value of enforcement to "0" (w:enforcement="0") <br/>
- */
- public void removeProtectionEnforcement() {
- settings.removeEnforcement();
- }
-
- }
|