123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- /* ====================================================================
- 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.math.BigInteger;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Spliterator;
-
- import org.apache.poi.ooxml.POIXMLDocumentPart;
- import org.apache.poi.util.Internal;
- import org.apache.xmlbeans.XmlCursor;
- import org.apache.xmlbeans.XmlObject;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
-
- /**
- * Base class for both bottom-of-the-page footnotes {@link XWPFFootnote} and end
- * notes {@link XWPFEndnote}).
- * <p>The only significant difference between footnotes and
- * end notes is which part they go on. Footnotes are managed by the Footnotes part
- * {@link XWPFFootnotes} and end notes are managed by the Endnotes part {@link XWPFEndnotes}.</p>
- * @since 4.0.0
- */
- public abstract class XWPFAbstractFootnoteEndnote implements Iterable<XWPFParagraph>, IBody {
-
- private final List<XWPFParagraph> paragraphs = new ArrayList<>();
- private final List<XWPFTable> tables = new ArrayList<>();
- private final List<XWPFPictureData> pictures = new ArrayList<>();
- private final List<IBodyElement> bodyElements = new ArrayList<>();
- protected CTFtnEdn ctFtnEdn;
- protected XWPFAbstractFootnotesEndnotes footnotes;
- protected XWPFDocument document;
-
- public XWPFAbstractFootnoteEndnote() {
- super();
- }
-
- @Internal
- protected XWPFAbstractFootnoteEndnote(XWPFDocument document, CTFtnEdn body) {
- ctFtnEdn = body;
- this.document = document;
- init();
- }
-
- @Internal
- protected XWPFAbstractFootnoteEndnote(CTFtnEdn note, XWPFAbstractFootnotesEndnotes footnotes) {
- this.footnotes = footnotes;
- ctFtnEdn = note;
- document = footnotes.getXWPFDocument();
- init();
- }
-
- protected void init() {
- XmlCursor cursor = ctFtnEdn.newCursor();
- //copied from XWPFDocument...should centralize this code
- //to avoid duplication
- cursor.selectPath("./*");
- while (cursor.toNextSelection()) {
- XmlObject o = cursor.getObject();
- if (o instanceof CTP) {
- XWPFParagraph p = new XWPFParagraph((CTP) o, this);
- bodyElements.add(p);
- paragraphs.add(p);
- } else if (o instanceof CTTbl) {
- XWPFTable t = new XWPFTable((CTTbl) o, this);
- bodyElements.add(t);
- tables.add(t);
- } else if (o instanceof CTSdtBlock) {
- XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this);
- bodyElements.add(c);
- }
-
- }
- cursor.dispose();
- }
-
- /**
- * Get the list of {@link XWPFParagraph}s in the footnote.
- * @return List of paragraphs
- */
- @Override
- public List<XWPFParagraph> getParagraphs() {
- return paragraphs;
- }
-
- /**
- * Get an iterator over the {@link XWPFParagraph}s in the footnote.
- * @return Iterator over the paragraph list.
- */
- @Override
- public Iterator<XWPFParagraph> iterator() {
- return paragraphs.iterator();
- }
-
- /**
- * Get a spliterator over the {@link XWPFParagraph}s in the footnote.
- * @return Spliterator over the paragraph list.
- *
- * @since POI 5.2.0
- */
- @Override
- public Spliterator<XWPFParagraph> spliterator() {
- return paragraphs.spliterator();
- }
-
- /**
- * Get the list of {@link XWPFTable}s in the footnote.
- * @return List of tables
- */
- @Override
- public List<XWPFTable> getTables() {
- return tables;
- }
-
- /**
- * Gets the list of {@link XWPFPictureData}s in the footnote.
- * @return List of pictures
- */
- public List<XWPFPictureData> getPictures() {
- return pictures;
- }
-
- /**
- * Gets the body elements ({@link IBodyElement}) of the footnote.
- * @return List of body elements.
- */
- @Override
- public List<IBodyElement> getBodyElements() {
- return bodyElements;
- }
-
- /**
- * Gets the underlying CTFtnEdn object for the footnote.
- * @return CTFtnEdn object
- */
- public CTFtnEdn getCTFtnEdn() {
- return ctFtnEdn;
- }
-
- /**
- * Set the underlying CTFtnEdn for the footnote.
- * <p>Use {@link XWPFDocument#createFootnote()} to create new footnotes.</p>
- * @param footnote The CTFtnEdn object that will underly the footnote.
- */
- public void setCTFtnEdn(CTFtnEdn footnote) {
- ctFtnEdn = footnote;
- }
-
- /**
- * Gets the {@link XWPFTable} at the specified position from the footnote's table array.
- * @param pos in table array
- * @return The {@link XWPFTable} at position pos, or null if there is no table at position pos.
- */
- @Override
- public XWPFTable getTableArray(int pos) {
- if (pos >= 0 && pos < tables.size()) {
- return tables.get(pos);
- }
- return null;
- }
-
- /**
- * Inserts an existing XWPFTable into the arrays bodyElements and tables.
- *
- * @param pos Position, in the bodyElements array, to insert the table
- * @param table XWPFTable to be inserted
- */
- @Override
- public void insertTable(int pos, XWPFTable table) {
- bodyElements.add(pos, table);
- int i = 0;
- for (CTTbl tbl : ctFtnEdn.getTblList()) {
- if (tbl == table.getCTTbl()) {
- break;
- }
- i++;
- }
- tables.add(i, table);
-
- }
-
- /**
- * if there is a corresponding {@link XWPFTable} of the parameter
- * ctTable in the tableList of this header
- * the method will return this table, or null if there is no
- * corresponding {@link XWPFTable}.
- */
- @Override
- public XWPFTable getTable(CTTbl ctTable) {
- for (XWPFTable table : tables) {
- if (table == null)
- return null;
- if (table.getCTTbl().equals(ctTable))
- return table;
- }
- return null;
- }
-
- @Override
- public XWPFParagraph getParagraph(CTP p) {
- for (XWPFParagraph paragraph : paragraphs) {
- if (paragraph.getCTP().equals(p))
- return paragraph;
- }
- return null;
- }
-
- /**
- * Returns the {@link XWPFParagraph} at position pos in footnote's paragraph array.
- * @param pos Array position of the paragraph to get.
- * @return the {@link XWPFParagraph} at position pos, or null if there is no paragraph at that position.
- */
- @Override
- public XWPFParagraph getParagraphArray(int pos) {
- if(pos >=0 && pos < paragraphs.size()) {
- return paragraphs.get(pos);
- }
- return null;
- }
-
- /**
- * get the {@link XWPFTableCell} that belongs to the CTTc cell.
- *
- * @return {@link XWPFTableCell} that corresponds to the CTTc cell, if there is one, otherwise null.
- */
- @Override
- public XWPFTableCell getTableCell(CTTc cell) {
- XmlCursor cursor = cell.newCursor();
- cursor.toParent();
- XmlObject o = cursor.getObject();
- if (!(o instanceof CTRow)) {
- return null;
- }
- CTRow row = (CTRow) o;
- cursor.toParent();
- o = cursor.getObject();
- cursor.dispose();
- if (!(o instanceof CTTbl)) {
- return null;
- }
- CTTbl tbl = (CTTbl) o;
- XWPFTable table = getTable(tbl);
- if (table == null) {
- return null;
- }
- XWPFTableRow tableRow = table.getRow(row);
- if(tableRow == null){
- return null;
- }
- return tableRow.getTableCell(cell);
- }
-
- /**
- * Verifies that cursor is on the right position.
- *
- * @return true if the cursor is within a CTFtnEdn element.
- */
- private boolean isCursorInFtn(XmlCursor cursor) {
- XmlCursor verify = cursor.newCursor();
- verify.toParent();
- boolean result = (verify.getObject() == this.ctFtnEdn);
- verify.dispose();
- return result;
- }
-
- /**
- * The owning object for this footnote
- *
- * @return The {@link XWPFFootnotes} object that contains this footnote.
- */
- public POIXMLDocumentPart getOwner() {
- return footnotes;
- }
-
- /**
- * Insert a table constructed from OOXML table markup.
- * @return the inserted {@link XWPFTable}
- */
- @Override
- public XWPFTable insertNewTbl(XmlCursor cursor) {
- if (isCursorInFtn(cursor)) {
- String uri = CTTbl.type.getName().getNamespaceURI();
- String localPart = "tbl";
- cursor.beginElement(localPart, uri);
- cursor.toParent();
- CTTbl t = (CTTbl) cursor.getObject();
- XWPFTable newT = new XWPFTable(t, this);
- cursor.removeXmlContents();
- XmlObject o = null;
- while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) {
- o = cursor.getObject();
- }
- if (!(o instanceof CTTbl)) {
- tables.add(0, newT);
- } else {
- int pos = tables.indexOf(getTable((CTTbl) o)) + 1;
- tables.add(pos, newT);
- }
- int i = 0;
- cursor = t.newCursor();
- while (cursor.toPrevSibling()) {
- o = cursor.getObject();
- if (o instanceof CTP || o instanceof CTTbl)
- i++;
- }
- bodyElements.add(i, newT);
- XmlCursor c2 = t.newCursor();
- cursor.toCursor(c2);
- cursor.toEndToken();
- c2.dispose();
- return newT;
- }
- return null;
- }
-
- /**
- * Add a new {@link XWPFParagraph} at position of the cursor.
- *
- * @return The inserted {@link XWPFParagraph}
- */
- @Override
- public XWPFParagraph insertNewParagraph(final XmlCursor cursor) {
- if (isCursorInFtn(cursor)) {
- String uri = CTP.type.getName().getNamespaceURI();
- String localPart = "p";
- cursor.beginElement(localPart, uri);
- cursor.toParent();
- CTP p = (CTP) cursor.getObject();
- XWPFParagraph newP = new XWPFParagraph(p, this);
- XmlObject o = null;
- while (!(o instanceof CTP) && (cursor.toPrevSibling())) {
- o = cursor.getObject();
- }
- if ((!(o instanceof CTP)) || o == p) {
- paragraphs.add(0, newP);
- } else {
- int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1;
- paragraphs.add(pos, newP);
- }
- int i = 0;
- XmlCursor p2 = p.newCursor();
- cursor.toCursor(p2);
- p2.dispose();
- while (cursor.toPrevSibling()) {
- o = cursor.getObject();
- if (o instanceof CTP || o instanceof CTTbl)
- i++;
- }
- bodyElements.add(i, newP);
- p2 = p.newCursor();
- cursor.toCursor(p2);
- cursor.toEndToken();
- p2.dispose();
- return newP;
- }
- return null;
- }
-
- /**
- * Add a new {@link XWPFTable} to the end of the footnote.
- *
- * @param table CTTbl object from which to construct the {@link XWPFTable}
- * @return The added {@link XWPFTable}
- */
- public XWPFTable addNewTbl(CTTbl table) {
- CTTbl newTable = ctFtnEdn.addNewTbl();
- newTable.set(table);
- XWPFTable xTable = new XWPFTable(newTable, this);
- tables.add(xTable);
- return xTable;
- }
-
- /**
- * Add a new {@link XWPFParagraph} to the end of the footnote.
- *
- * @param paragraph CTP paragraph from which to construct the {@link XWPFParagraph}
- * @return The added {@link XWPFParagraph}
- */
- public XWPFParagraph addNewParagraph(CTP paragraph) {
- CTP newPara = ctFtnEdn.addNewP();
- newPara.set(paragraph);
- XWPFParagraph xPara = new XWPFParagraph(newPara, this);
- paragraphs.add(xPara);
- return xPara;
- }
-
- /**
- * Get the {@link XWPFDocument} the footnote is part of.
- */
- @Override
- public XWPFDocument getXWPFDocument() {
- return document;
- }
-
- /**
- * Get the Part to which the footnote belongs, which you need for adding relationships to other parts
- * @return {@link POIXMLDocumentPart} that contains the footnote.
- */
- @Override
- public POIXMLDocumentPart getPart() {
- return footnotes;
- }
-
- /**
- * Get the part type {@link BodyType} of the footnote.
- * @return The {@link BodyType} value.
- */
- @Override
- public BodyType getPartType() {
- return BodyType.FOOTNOTE;
- }
-
- /**
- * Get the ID of the footnote.
- * <p>Footnote IDs are unique across all bottom-of-the-page and
- * end note footnotes.</p>
- *
- * @return Footnote ID
- * @since 4.0.0
- */
- public BigInteger getId() {
- return this.ctFtnEdn.getId();
- }
-
- /**
- * Appends a new {@link XWPFParagraph} to this footnote.
- *
- * @return The new {@link XWPFParagraph}
- * @since 4.0.0
- */
- public XWPFParagraph createParagraph() {
- XWPFParagraph p = new XWPFParagraph(this.ctFtnEdn.addNewP(), this);
- paragraphs.add(p);
- bodyElements.add(p);
-
- // If the paragraph is the first paragraph in the footnote,
- // ensure that it has a footnote reference run.
-
- if (p.equals(getParagraphs().get(0))) {
- ensureFootnoteRef(p);
- }
- return p;
- }
-
- /**
- * Ensure that the specified paragraph has a reference marker for this
- * footnote by adding a footnote reference if one is not found.
- * <p>This method is for the first paragraph in the footnote, not
- * paragraphs that will refer to the footnote. For references to
- * the footnote, use {@link XWPFParagraph#addFootnoteReference(XWPFAbstractFootnoteEndnote)}.
- * </p>
- * <p>The first run of the first paragraph in a footnote should
- * contain a {@link CTFtnEdnRef} object.</p>
- *
- * @param p The {@link XWPFParagraph} to ensure
- * @since 4.0.0
- */
- public abstract void ensureFootnoteRef(XWPFParagraph p);
-
- /**
- * Appends a new {@link XWPFTable} to this footnote
- *
- * @return The new {@link XWPFTable}
- * @since 4.0.0
- */
- public XWPFTable createTable() {
- XWPFTable table = new XWPFTable(ctFtnEdn.addNewTbl(), this);
- if (bodyElements.size() == 0) {
- XWPFParagraph p = createParagraph();
- ensureFootnoteRef(p);
- }
- bodyElements.add(table);
- tables.add(table);
- return table;
- }
-
- /**
- * Appends a new {@link XWPFTable} to this footnote
- * @param rows Number of rows to initialize the table with
- * @param cols Number of columns to initialize the table with
- * @return the new {@link XWPFTable} with the specified number of rows and columns
- * @since 4.0.0
- */
- public XWPFTable createTable(int rows, int cols) {
- XWPFTable table = new XWPFTable(ctFtnEdn.addNewTbl(), this, rows, cols);
- bodyElements.add(table);
- tables.add(table);
- return table;
- }
-
- }
|