[github-115] implement endnote. This closes #115
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1836538 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f4decbdb32
commit
e3ae88792b
@ -0,0 +1,499 @@
|
|||||||
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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.CTR;
|
||||||
|
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 AbstractXWPFFootnoteEndnote implements Iterable<XWPFParagraph>, IBody {
|
||||||
|
|
||||||
|
private List<XWPFParagraph> paragraphs = new ArrayList<>();
|
||||||
|
private List<XWPFTable> tables = new ArrayList<>();
|
||||||
|
private List<XWPFPictureData> pictures = new ArrayList<>();
|
||||||
|
private List<IBodyElement> bodyElements = new ArrayList<>();
|
||||||
|
protected CTFtnEdn ctFtnEdn;
|
||||||
|
protected AbstractXWPFFootnotesEndnotes footnotes;
|
||||||
|
protected XWPFDocument document;
|
||||||
|
|
||||||
|
public AbstractXWPFFootnoteEndnote() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
protected AbstractXWPFFootnoteEndnote(XWPFDocument document, CTFtnEdn body) {
|
||||||
|
ctFtnEdn = body;
|
||||||
|
this.document = document;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
protected AbstractXWPFFootnoteEndnote(CTFtnEdn note, AbstractXWPFFootnotesEndnotes 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
|
||||||
|
*/
|
||||||
|
public List<XWPFParagraph> getParagraphs() {
|
||||||
|
return paragraphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an iterator over the {@link XWPFParagraph}s in the footnote.
|
||||||
|
* @return Iterator over the paragraph list.
|
||||||
|
*/
|
||||||
|
public Iterator<XWPFParagraph> iterator() {
|
||||||
|
return paragraphs.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of {@link XWPFTable}s in the footnote.
|
||||||
|
* @return List of tables
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int)
|
||||||
|
*/
|
||||||
|
public XWPFTable getTableArray(int pos) {
|
||||||
|
if (pos >= 0 && pos < tables.size()) {
|
||||||
|
return tables.get(pos);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an existing {@link XWPFTable) into the arrays bodyElements and tables.
|
||||||
|
*
|
||||||
|
* @param pos Position, in the bodyElements array, to insert the table
|
||||||
|
* @param table {@link XWPFTable) to be inserted
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table)
|
||||||
|
*/
|
||||||
|
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}.
|
||||||
|
*
|
||||||
|
* @param ctTable
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable)
|
||||||
|
*/
|
||||||
|
public XWPFTable getTable(CTTbl ctTable) {
|
||||||
|
for (XWPFTable table : tables) {
|
||||||
|
if (table == null)
|
||||||
|
return null;
|
||||||
|
if (table.getCTTbl().equals(ctTable))
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if there is a corresponding {@link XWPFParagraph} of the parameter p in the paragraphList of this header or footer
|
||||||
|
* the method will return that paragraph, otherwise the method will return null.
|
||||||
|
*
|
||||||
|
* @param p The CTP paragraph to find the corresponding {@link XWPFParagraph} for.
|
||||||
|
* @return The {@link XWPFParagraph} that corresponds to the CTP paragraph in the paragraph
|
||||||
|
* list of this footnote or null if no paragraph is found.
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p)
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos)
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param cell
|
||||||
|
* @return {@link XWPFTableCell} that corresponds to the CTTc cell, if there is one, otherwise null.
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell)
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param cursor
|
||||||
|
* @return true if the cursor is within a CTFtnEdn element.
|
||||||
|
*/
|
||||||
|
private boolean isCursorInFtn(XmlCursor cursor) {
|
||||||
|
XmlCursor verify = cursor.newCursor();
|
||||||
|
verify.toParent();
|
||||||
|
if (verify.getObject() == this.ctFtnEdn) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @param cursor
|
||||||
|
* @return the inserted {@link XWPFTable}
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor)
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param cursor
|
||||||
|
* @return The inserted {@link XWPFParagraph}
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor)
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument()
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
||||||
|
*/
|
||||||
|
public POIXMLDocumentPart getPart() {
|
||||||
|
return footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the part type {@link BodyType} of the footnote.
|
||||||
|
* @return The {@link BodyType} value.
|
||||||
|
*
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
|
||||||
|
*/
|
||||||
|
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(XWPFFootnote)}.
|
||||||
|
* </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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||||
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for the Footnotes and Endnotes part implementations.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractXWPFFootnotesEndnotes extends POIXMLDocumentPart {
|
||||||
|
|
||||||
|
protected XWPFDocument document;
|
||||||
|
protected List<AbstractXWPFFootnoteEndnote> listFootnote = new ArrayList<>();
|
||||||
|
private FootnoteEndnoteIdManager idManager;
|
||||||
|
|
||||||
|
public AbstractXWPFFootnotesEndnotes(OPCPackage pkg) {
|
||||||
|
super(pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractXWPFFootnotesEndnotes(OPCPackage pkg,
|
||||||
|
String coreDocumentRel) {
|
||||||
|
super(pkg, coreDocumentRel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractXWPFFootnotesEndnotes() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractXWPFFootnotesEndnotes(PackagePart part) {
|
||||||
|
super(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractXWPFFootnotesEndnotes(POIXMLDocumentPart parent, PackagePart part) {
|
||||||
|
super(parent, part);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractXWPFFootnoteEndnote getFootnoteById(int id) {
|
||||||
|
for (AbstractXWPFFootnoteEndnote note : listFootnote) {
|
||||||
|
if (note.getCTFtnEdn().getId().intValue() == id)
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
||||||
|
*/
|
||||||
|
public XWPFDocument getXWPFDocument() {
|
||||||
|
if (document != null) {
|
||||||
|
return document;
|
||||||
|
} else {
|
||||||
|
return (XWPFDocument) getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setXWPFDocument(XWPFDocument doc) {
|
||||||
|
document = doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdManager(FootnoteEndnoteIdManager footnoteIdManager) {
|
||||||
|
this.idManager = footnoteIdManager;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public FootnoteEndnoteIdManager getIdManager() {
|
||||||
|
return this.idManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages IDs for footnotes and endnotes.
|
||||||
|
* <p>Footnotes and endnotes are managed in separate parts but
|
||||||
|
* represent a single namespace of IDs.</p>
|
||||||
|
*/
|
||||||
|
public class FootnoteEndnoteIdManager {
|
||||||
|
|
||||||
|
private XWPFDocument document;
|
||||||
|
|
||||||
|
public FootnoteEndnoteIdManager(XWPFDocument document) {
|
||||||
|
this.document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next ID number.
|
||||||
|
*
|
||||||
|
* @return ID number to use.
|
||||||
|
*/
|
||||||
|
public BigInteger nextId() {
|
||||||
|
|
||||||
|
List<BigInteger> ids = new ArrayList<BigInteger>();
|
||||||
|
for (AbstractXWPFFootnoteEndnote note : document.getFootnotes()) {
|
||||||
|
ids.add(note.getId());
|
||||||
|
}
|
||||||
|
for (AbstractXWPFFootnoteEndnote note : document.getEndnotes()) {
|
||||||
|
ids.add(note.getId());
|
||||||
|
}
|
||||||
|
int cand = ids.size();
|
||||||
|
BigInteger newId = BigInteger.valueOf(cand);
|
||||||
|
while (ids.contains(newId)) {
|
||||||
|
cand++;
|
||||||
|
newId = BigInteger.valueOf(cand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -54,11 +54,9 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
|||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.ooxml.util.IdentifierManager;
|
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.poi.ooxml.util.PackageHelper;
|
|
||||||
import org.apache.poi.wp.usermodel.HeaderFooterType;
|
import org.apache.poi.wp.usermodel.HeaderFooterType;
|
||||||
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
||||||
import org.apache.xmlbeans.XmlCursor;
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
@ -100,6 +98,7 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
|||||||
* http://www.ecma-international.org/publications/standards/Ecma-376.htm
|
* http://www.ecma-international.org/publications/standards/Ecma-376.htm
|
||||||
* at some point in your use.</p>
|
* at some point in your use.</p>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(XWPFDocument.class);
|
private static final POILogger LOG = POILogFactory.getLogger(XWPFDocument.class);
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
protected List<IBodyElement> bodyElements = new ArrayList<>();
|
protected List<IBodyElement> bodyElements = new ArrayList<>();
|
||||||
protected List<XWPFPictureData> pictures = new ArrayList<>();
|
protected List<XWPFPictureData> pictures = new ArrayList<>();
|
||||||
protected Map<Long, List<XWPFPictureData>> packagePictures = new HashMap<>();
|
protected Map<Long, List<XWPFPictureData>> packagePictures = new HashMap<>();
|
||||||
protected Map<Integer, XWPFFootnote> endnotes = new HashMap<>();
|
protected XWPFEndnotes endnotes;
|
||||||
protected XWPFNumbering numbering;
|
protected XWPFNumbering numbering;
|
||||||
protected XWPFStyles styles;
|
protected XWPFStyles styles;
|
||||||
protected XWPFFootnotes footnotes;
|
protected XWPFFootnotes footnotes;
|
||||||
@ -124,6 +123,9 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
* Keeps track on all id-values used in this document and included parts, like headers, footers, etc.
|
* Keeps track on all id-values used in this document and included parts, like headers, footers, etc.
|
||||||
*/
|
*/
|
||||||
private IdentifierManager drawingIdManager = new IdentifierManager(0L, 4294967295L);
|
private IdentifierManager drawingIdManager = new IdentifierManager(0L, 4294967295L);
|
||||||
|
|
||||||
|
private FootnoteEndnoteIdManager footnoteIdManager = new FootnoteEndnoteIdManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the joy of different headers/footers for different pages
|
* Handles the joy of different headers/footers for different pages
|
||||||
*/
|
*/
|
||||||
@ -286,12 +288,11 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
if (relation.equals(XWPFRelation.FOOTNOTE.getRelation())) {
|
if (relation.equals(XWPFRelation.FOOTNOTE.getRelation())) {
|
||||||
this.footnotes = (XWPFFootnotes) p;
|
this.footnotes = (XWPFFootnotes) p;
|
||||||
this.footnotes.onDocumentRead();
|
this.footnotes.onDocumentRead();
|
||||||
|
this.footnotes.setIdManager(footnoteIdManager);
|
||||||
} else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())) {
|
} else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())) {
|
||||||
EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS);
|
this.endnotes = (XWPFEndnotes) p;
|
||||||
|
this.endnotes.onDocumentRead();
|
||||||
for (CTFtnEdn ctFtnEdn : endnotesDocument.getEndnotes().getEndnoteArray()) {
|
this.endnotes.setIdManager(footnoteIdManager);
|
||||||
endnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,14 +417,14 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
if (footnotes == null) {
|
if (footnotes == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return footnotes.getFootnoteById(id);
|
return (XWPFFootnote)footnotes.getFootnoteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public XWPFFootnote getEndnoteByID(int id) {
|
public XWPFEndnote getEndnoteByID(int id) {
|
||||||
if (endnotes == null) {
|
if (endnotes == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return endnotes.get(id);
|
return endnotes.getFootnoteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<XWPFFootnote> getFootnotes() {
|
public List<XWPFFootnote> getFootnotes() {
|
||||||
@ -898,19 +899,34 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
|
|
||||||
XWPFFootnotes wrapper = (XWPFFootnotes) createRelationship(relation, XWPFFactory.getInstance(), i);
|
XWPFFootnotes wrapper = (XWPFFootnotes) createRelationship(relation, XWPFFactory.getInstance(), i);
|
||||||
wrapper.setFootnotes(footnotesDoc.addNewFootnotes());
|
wrapper.setFootnotes(footnotesDoc.addNewFootnotes());
|
||||||
|
wrapper.setIdManager(this.footnoteIdManager);
|
||||||
footnotes = wrapper;
|
footnotes = wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
return footnotes;
|
return footnotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a CTFtnEdn footnote to the document.
|
||||||
|
*
|
||||||
|
* @param note CTFtnEnd to be added.
|
||||||
|
* @return New {@link XWPFFootnote}
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
||||||
return footnotes.addFootnote(note);
|
return footnotes.addFootnote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public XWPFFootnote addEndnote(CTFtnEdn note) {
|
/**
|
||||||
XWPFFootnote endnote = new XWPFFootnote(this, note);
|
* Add a CTFtnEdn endnote to the document.
|
||||||
endnotes.put(note.getId().intValue(), endnote);
|
*
|
||||||
|
* @param note CTFtnEnd to be added.
|
||||||
|
* @return New {@link XWPFEndnote}
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public XWPFEndnote addEndnote(CTFtnEdn note) {
|
||||||
|
XWPFEndnote endnote = new XWPFEndnote(this, note);
|
||||||
|
endnotes.addEndnote(note);
|
||||||
return endnote;
|
return endnote;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1658,12 +1674,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new footnote and add it to the document.
|
* Create a new footnote and add it to the document.
|
||||||
* <p>The new note will have one paragraph with the style "FootnoteText"
|
|
||||||
* and one run containing the required footnote reference with the
|
|
||||||
* style "FootnoteReference".
|
|
||||||
*
|
*
|
||||||
* @return New XWPFFootnote.
|
* @return New XWPFFootnote.
|
||||||
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public XWPFFootnote createFootnote() {
|
public XWPFFootnote createFootnote() {
|
||||||
XWPFFootnotes footnotes = this.createFootnotes();
|
XWPFFootnotes footnotes = this.createFootnotes();
|
||||||
@ -1675,8 +1689,9 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
/**
|
/**
|
||||||
* Remove the specified footnote if present.
|
* Remove the specified footnote if present.
|
||||||
*
|
*
|
||||||
* @param pos
|
* @param pos Array position of the footnote to be removed.
|
||||||
* @return True if the footnote was removed.
|
* @return True if the footnote was removed.
|
||||||
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public boolean removeFootnote(int pos) {
|
public boolean removeFootnote(int pos) {
|
||||||
if (null != footnotes) {
|
if (null != footnotes) {
|
||||||
@ -1685,4 +1700,62 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new end note and add it to the document.
|
||||||
|
*
|
||||||
|
* @return New {@link XWPFEndnote}.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public XWPFEndnote createEndnote() {
|
||||||
|
XWPFEndnotes endnotes = this.createEndnotes();
|
||||||
|
|
||||||
|
XWPFEndnote endnote = endnotes.createEndnote();
|
||||||
|
return endnote;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public XWPFEndnotes createEndnotes() {
|
||||||
|
if (endnotes == null) {
|
||||||
|
EndnotesDocument endnotesDoc = EndnotesDocument.Factory.newInstance();
|
||||||
|
|
||||||
|
XWPFRelation relation = XWPFRelation.ENDNOTE;
|
||||||
|
int i = getRelationIndex(relation);
|
||||||
|
|
||||||
|
XWPFEndnotes wrapper = (XWPFEndnotes) createRelationship(relation, XWPFFactory.getInstance(), i);
|
||||||
|
wrapper.setEndnotes(endnotesDoc.addNewEndnotes());
|
||||||
|
wrapper.setIdManager(footnoteIdManager);
|
||||||
|
endnotes = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
return endnotes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of end notes for the document.
|
||||||
|
*
|
||||||
|
* @return List, possibly empty, of {@link XWPFEndnote}s.
|
||||||
|
*/
|
||||||
|
public List<XWPFEndnote> getEndnotes() {
|
||||||
|
if (endnotes == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return endnotes.getEndnotesList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified end note if present.
|
||||||
|
*
|
||||||
|
* @param pos Array position of the end note to be removed.
|
||||||
|
* @return True if the end note was removed.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public boolean removeEndnote(int pos) {
|
||||||
|
if (null != endnotes) {
|
||||||
|
return endnotes.removeEndnote(pos);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an end note footnote.
|
||||||
|
* <p>End notes are collected at the end of a document or section rather than
|
||||||
|
* at the bottom of a page.</p>
|
||||||
|
* <p>Create a new footnote using {@link XWPFDocument#createEndnote()} or
|
||||||
|
* {@link XWPFEndnotes#createFootnote()}.</p>
|
||||||
|
* <p>The first body element of a footnote should (or possibly must) be a paragraph
|
||||||
|
* with the first run containing a CTFtnEdnRef object. The {@link XWPFFootnote#createParagraph()}
|
||||||
|
* and {@link XWPFFootnote#createTable()} methods do this for you.</p>
|
||||||
|
* <p>Footnotes have IDs that are unique across all footnotes in the document. You use
|
||||||
|
* the footnote ID to create a reference to a footnote from within a paragraph.</p>
|
||||||
|
* <p>To create a reference to a footnote within a paragraph you create a run
|
||||||
|
* with a CTFtnEdnRef that specifies the ID of the target paragraph.
|
||||||
|
* The {@link XWPFParagraph#addFootnoteReference(AbstractXWPFFootnoteEndnote)}
|
||||||
|
* method does this for you.</p>
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public class XWPFEndnote extends AbstractXWPFFootnoteEndnote {
|
||||||
|
|
||||||
|
public XWPFEndnote() {}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public XWPFEndnote(XWPFDocument document, CTFtnEdn body) {
|
||||||
|
super(document, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public XWPFEndnote(CTFtnEdn note, AbstractXWPFFootnotesEndnotes footnotes) {
|
||||||
|
super(note, footnotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the specified paragraph has a reference marker for this
|
||||||
|
* end note 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(AbstractXWPFFootnoteEndnote))}.
|
||||||
|
* </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 void ensureFootnoteRef(XWPFParagraph p) {
|
||||||
|
|
||||||
|
XWPFRun r = null;
|
||||||
|
if (p.getRuns().size() > 0) {
|
||||||
|
r = p.getRuns().get(0);
|
||||||
|
}
|
||||||
|
if (r == null) {
|
||||||
|
r = p.createRun();
|
||||||
|
}
|
||||||
|
CTR ctr = r.getCTR();
|
||||||
|
boolean foundRef = false;
|
||||||
|
for (CTFtnEdnRef ref : ctr.getEndnoteReferenceList()) {
|
||||||
|
if (getId().equals(ref.getId())) {
|
||||||
|
foundRef = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundRef) {
|
||||||
|
ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
|
||||||
|
ctr.addNewEndnoteRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
195
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFEndnotes.java
Normal file
195
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFEndnotes.java
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
|
import org.apache.poi.ooxml.POIXMLException;
|
||||||
|
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTEndnotes;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.EndnotesDocument;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks after the collection of end notes for a document.
|
||||||
|
* Managed end notes ({@link XWPFEndnote}).
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public class XWPFEndnotes extends AbstractXWPFFootnotesEndnotes {
|
||||||
|
|
||||||
|
protected CTEndnotes ctEndnotes;
|
||||||
|
|
||||||
|
public XWPFEndnotes() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct XWPFEndnotes from a package part
|
||||||
|
*
|
||||||
|
* @param part the package part holding the data of the footnotes,
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta1
|
||||||
|
*/
|
||||||
|
public XWPFEndnotes(PackagePart part) throws IOException, OpenXML4JException {
|
||||||
|
super(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the end notes for this part.
|
||||||
|
*
|
||||||
|
* @param endnotes The endnotes to be added.
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public void setEndnotes(CTEndnotes endnotes) {
|
||||||
|
ctEndnotes = endnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new end note and add it to the document.
|
||||||
|
*
|
||||||
|
* @return New XWPFEndnote
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public XWPFEndnote createEndnote() {
|
||||||
|
CTFtnEdn newNote = CTFtnEdn.Factory.newInstance();
|
||||||
|
newNote.setType(STFtnEdn.NORMAL);
|
||||||
|
|
||||||
|
XWPFEndnote footnote = addEndnote(newNote);
|
||||||
|
footnote.getCTFtnEdn().setId(getIdManager().nextId());
|
||||||
|
return footnote;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified footnote if present.
|
||||||
|
*
|
||||||
|
* @param pos
|
||||||
|
* @return True if the footnote was removed.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public boolean removeFootnote(int pos) {
|
||||||
|
if (ctEndnotes.sizeOfEndnoteArray() >= pos - 1) {
|
||||||
|
ctEndnotes.removeEndnote(pos);
|
||||||
|
listFootnote.remove(pos);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read document
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onDocumentRead() throws IOException {
|
||||||
|
EndnotesDocument notesDoc;
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = getPackagePart().getInputStream();
|
||||||
|
notesDoc = EndnotesDocument.Factory.parse(is, DEFAULT_XML_OPTIONS);
|
||||||
|
ctEndnotes = notesDoc.getEndnotes();
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new POIXMLException();
|
||||||
|
} finally {
|
||||||
|
if (is != null) {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CTFtnEdn note : ctEndnotes.getEndnoteList()) {
|
||||||
|
listFootnote.add(new XWPFEndnote(note, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void commit() throws IOException {
|
||||||
|
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
|
||||||
|
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTEndnotes.type.getName().getNamespaceURI(), "endnotes"));
|
||||||
|
PackagePart part = getPackagePart();
|
||||||
|
OutputStream out = part.getOutputStream();
|
||||||
|
ctEndnotes.save(out, xmlOptions);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add an {@link XWPFEndnote} to the document
|
||||||
|
*
|
||||||
|
* @param endnote
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void addEndnote(XWPFEndnote endnote) {
|
||||||
|
listFootnote.add(endnote);
|
||||||
|
ctEndnotes.addNewEndnote().set(endnote.getCTFtnEdn());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an endnote to the document
|
||||||
|
*
|
||||||
|
* @param note Note to add
|
||||||
|
* @return New {@link XWPFEndnote}
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public XWPFEndnote addEndnote(CTFtnEdn note) {
|
||||||
|
CTFtnEdn newNote = ctEndnotes.addNewEndnote();
|
||||||
|
newNote.set(note);
|
||||||
|
XWPFEndnote xNote = new XWPFEndnote(newNote, this);
|
||||||
|
listFootnote.add(xNote);
|
||||||
|
return xNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the end note with the specified ID, if any.
|
||||||
|
* @param id End note ID.
|
||||||
|
* @return The end note or null if not found.
|
||||||
|
*/
|
||||||
|
public XWPFEndnote getFootnoteById(int id) {
|
||||||
|
return (XWPFEndnote)super.getFootnoteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of {@link XWPFEndnote} in the Endnotes part.
|
||||||
|
*
|
||||||
|
* @return List, possibly empty, of end notes.
|
||||||
|
*/
|
||||||
|
public List<XWPFEndnote> getEndnotesList() {
|
||||||
|
List<XWPFEndnote> resultList = new ArrayList<XWPFEndnote>();
|
||||||
|
for (AbstractXWPFFootnoteEndnote note : listFootnote) {
|
||||||
|
resultList.add((XWPFEndnote)note);
|
||||||
|
}
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified end note if present.
|
||||||
|
*
|
||||||
|
* @param pos Array position of the endnote to be removed
|
||||||
|
* @return True if the end note was removed.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public boolean removeEndnote(int pos) {
|
||||||
|
if (ctEndnotes.sizeOfEndnoteArray() >= pos - 1) {
|
||||||
|
ctEndnotes.removeEndnote(pos);
|
||||||
|
listFootnote.remove(pos);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -16,22 +16,10 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xwpf.usermodel;
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import org.apache.poi.util.Internal;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
|
||||||
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.CTFtnEdn;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a bottom-of-the-page footnote.
|
* Represents a bottom-of-the-page footnote.
|
||||||
@ -44,425 +32,21 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
|
|||||||
* the footnote ID to create a reference to a footnote from within a paragraph.</p>
|
* the footnote ID to create a reference to a footnote from within a paragraph.</p>
|
||||||
* <p>To create a reference to a footnote within a paragraph you create a run
|
* <p>To create a reference to a footnote within a paragraph you create a run
|
||||||
* with a CTFtnEdnRef that specifies the ID of the target paragraph.
|
* with a CTFtnEdnRef that specifies the ID of the target paragraph.
|
||||||
* The {@link XWPFParagraph#addFootnoteReference(XWPFFootnote)}
|
* The {@link XWPFParagraph#addFootnoteReference(AbstractXWPFFootnoteEndnote)}
|
||||||
* method does this for you.</p>
|
* method does this for you.</p>
|
||||||
*/
|
*/
|
||||||
public class XWPFFootnote implements Iterable<XWPFParagraph>, IBody {
|
public class XWPFFootnote extends AbstractXWPFFootnoteEndnote {
|
||||||
private List<XWPFParagraph> paragraphs = new ArrayList<>();
|
|
||||||
private List<XWPFTable> tables = new ArrayList<>();
|
@Internal
|
||||||
private List<XWPFPictureData> pictures = new ArrayList<>();
|
public XWPFFootnote(CTFtnEdn note, AbstractXWPFFootnotesEndnotes xFootnotes) {
|
||||||
private List<IBodyElement> bodyElements = new ArrayList<>();
|
super(note, xFootnotes);
|
||||||
|
|
||||||
private CTFtnEdn ctFtnEdn;
|
|
||||||
private XWPFFootnotes footnotes;
|
|
||||||
private XWPFDocument document;
|
|
||||||
|
|
||||||
public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) {
|
|
||||||
footnotes = xFootnotes;
|
|
||||||
ctFtnEdn = note;
|
|
||||||
document = xFootnotes.getXWPFDocument();
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
public XWPFFootnote(XWPFDocument document, CTFtnEdn body) {
|
public XWPFFootnote(XWPFDocument document, CTFtnEdn body) {
|
||||||
ctFtnEdn = body;
|
super(document, body);
|
||||||
this.document = document;
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private 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
|
|
||||||
*/
|
|
||||||
public List<XWPFParagraph> getParagraphs() {
|
|
||||||
return paragraphs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an iterator over the {@link XWPFParagraph}s in the footnote.
|
|
||||||
* @return Iterator over the paragraph list.
|
|
||||||
*/
|
|
||||||
public Iterator<XWPFParagraph> iterator() {
|
|
||||||
return paragraphs.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of {@link XWPFTable}s in the footnote.
|
|
||||||
* @return List of tables
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int)
|
|
||||||
*/
|
|
||||||
public XWPFTable getTableArray(int pos) {
|
|
||||||
if (pos >= 0 && pos < tables.size()) {
|
|
||||||
return tables.get(pos);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts an existing {@link XWPFTable) into the arrays bodyElements and tables.
|
|
||||||
*
|
|
||||||
* @param pos Position, in the bodyElements array, to insert the table
|
|
||||||
* @param table {@link XWPFTable) to be inserted
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table)
|
|
||||||
*/
|
|
||||||
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}.
|
|
||||||
*
|
|
||||||
* @param ctTable
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable)
|
|
||||||
*/
|
|
||||||
public XWPFTable getTable(CTTbl ctTable) {
|
|
||||||
for (XWPFTable table : tables) {
|
|
||||||
if (table == null)
|
|
||||||
return null;
|
|
||||||
if (table.getCTTbl().equals(ctTable))
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if there is a corresponding {@link XWPFParagraph} of the parameter p in the paragraphList of this header or footer
|
|
||||||
* the method will return that paragraph, otherwise the method will return null.
|
|
||||||
*
|
|
||||||
* @param p The CTP paragraph to find the corresponding {@link XWPFParagraph} for.
|
|
||||||
* @return The {@link XWPFParagraph} that corresponds to the CTP paragraph in the paragraph
|
|
||||||
* list of this footnote or null if no paragraph is found.
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p)
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos)
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @param cell
|
|
||||||
* @return {@link XWPFTableCell} that corresponds to the CTTc cell, if there is one, otherwise null.
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell)
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @param cursor
|
|
||||||
* @return true if the cursor is within a CTFtnEdn element.
|
|
||||||
*/
|
|
||||||
private boolean isCursorInFtn(XmlCursor cursor) {
|
|
||||||
XmlCursor verify = cursor.newCursor();
|
|
||||||
verify.toParent();
|
|
||||||
if (verify.getObject() == this.ctFtnEdn) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* @param cursor
|
|
||||||
* @return the inserted {@link XWPFTable}
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor)
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @param cursor
|
|
||||||
* @return The inserted {@link XWPFParagraph}
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor)
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument()
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
|
||||||
*/
|
|
||||||
public POIXMLDocumentPart getPart() {
|
|
||||||
return footnotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the part type {@link BodyType} of the footnote.
|
|
||||||
* @return The {@link BodyType} value.
|
|
||||||
*
|
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
public BigInteger getId() {
|
|
||||||
return this.ctFtnEdn.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a new {@link XWPFParagraph} to this footnote.
|
|
||||||
*
|
|
||||||
* @return The new {@link XWPFParagraph}
|
|
||||||
*/
|
|
||||||
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
|
* Ensure that the specified paragraph has a reference marker for this
|
||||||
* footnote by adding a footnote reference if one is not found.
|
* footnote by adding a footnote reference if one is not found.
|
||||||
@ -474,7 +58,8 @@ public class XWPFFootnote implements Iterable<XWPFParagraph>, IBody {
|
|||||||
* contain a {@link CTFtnEdnRef} object.</p>
|
* contain a {@link CTFtnEdnRef} object.</p>
|
||||||
*
|
*
|
||||||
* @param p The {@link XWPFParagraph} to ensure
|
* @param p The {@link XWPFParagraph} to ensure
|
||||||
*/
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
public void ensureFootnoteRef(XWPFParagraph p) {
|
public void ensureFootnoteRef(XWPFParagraph p) {
|
||||||
|
|
||||||
XWPFRun r = null;
|
XWPFRun r = null;
|
||||||
@ -496,34 +81,6 @@ public class XWPFFootnote implements Iterable<XWPFParagraph>, IBody {
|
|||||||
ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
|
ctr.addNewRPr().addNewRStyle().setVal("FootnoteReference");
|
||||||
ctr.addNewFootnoteRef();
|
ctr.addNewFootnoteRef();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends a new {@link XWPFTable} to this footnote
|
|
||||||
*
|
|
||||||
* @return The new {@link XWPFTable}
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
public XWPFTable createTable(int rows, int cols) {
|
|
||||||
XWPFTable table = new XWPFTable(ctFtnEdn.addNewTbl(), this, rows, cols);
|
|
||||||
bodyElements.add(table);
|
|
||||||
tables.add(table);
|
|
||||||
return table;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,27 +28,23 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
|
||||||
import org.apache.poi.ooxml.POIXMLException;
|
import org.apache.poi.ooxml.POIXMLException;
|
||||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks after the collection of Footnotes for a document.
|
* Looks after the collection of Footnotes for a document.
|
||||||
* Manages both bottom-of-the-page footnotes and end notes.
|
* Manages bottom-of-the-page footnotes ({@link XWPFFootnote}).
|
||||||
*/
|
*/
|
||||||
public class XWPFFootnotes extends POIXMLDocumentPart {
|
public class XWPFFootnotes extends AbstractXWPFFootnotesEndnotes {
|
||||||
protected XWPFDocument document;
|
protected CTFootnotes ctFootnotes;
|
||||||
private List<XWPFFootnote> listFootnote = new ArrayList<>();
|
|
||||||
private CTFootnotes ctFootnotes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct XWPFFootnotes from a package part
|
* Construct XWPFFootnotes from a package part
|
||||||
@ -67,6 +63,49 @@ public class XWPFFootnotes extends POIXMLDocumentPart {
|
|||||||
public XWPFFootnotes() {
|
public XWPFFootnotes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ctFootnotes
|
||||||
|
*
|
||||||
|
* @param footnotes Collection of CTFntEdn objects.
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public void setFootnotes(CTFootnotes footnotes) {
|
||||||
|
ctFootnotes = footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new footnote and add it to the document.
|
||||||
|
*
|
||||||
|
* @return New {@link XWPFFootnote}
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public XWPFFootnote createFootnote() {
|
||||||
|
CTFtnEdn newNote = CTFtnEdn.Factory.newInstance();
|
||||||
|
newNote.setType(STFtnEdn.NORMAL);
|
||||||
|
|
||||||
|
XWPFFootnote footnote = addFootnote(newNote);
|
||||||
|
footnote.getCTFtnEdn().setId(getIdManager().nextId());
|
||||||
|
return footnote;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified footnote if present.
|
||||||
|
*
|
||||||
|
* @param pos Array position of the footnote to be removed
|
||||||
|
* @return True if the footnote was removed.
|
||||||
|
* @since 4.0.0
|
||||||
|
*/
|
||||||
|
public boolean removeFootnote(int pos) {
|
||||||
|
if (ctFootnotes.sizeOfFootnoteArray() >= pos - 1) {
|
||||||
|
ctFootnotes.removeFootnote(pos);
|
||||||
|
listFootnote.remove(pos);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read document
|
* Read document
|
||||||
*/
|
*/
|
||||||
@ -85,9 +124,8 @@ public class XWPFFootnotes extends POIXMLDocumentPart {
|
|||||||
is.close();
|
is.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find our footnotes
|
for (CTFtnEdn note : ctFootnotes.getFootnoteList()) {
|
||||||
for (CTFtnEdn note : ctFootnotes.getFootnoteArray()) {
|
|
||||||
listFootnote.add(new XWPFFootnote(note, this));
|
listFootnote.add(new XWPFFootnote(note, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,31 +140,10 @@ public class XWPFFootnotes extends POIXMLDocumentPart {
|
|||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<XWPFFootnote> getFootnotesList() {
|
|
||||||
return listFootnote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XWPFFootnote getFootnoteById(int id) {
|
|
||||||
for (XWPFFootnote note : listFootnote) {
|
|
||||||
if (note.getCTFtnEdn().getId().intValue() == id)
|
|
||||||
return note;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the ctFootnotes
|
* Add an {@link XWPFFootnote} to the document
|
||||||
*
|
*
|
||||||
* @param footnotes
|
* @param footnote Footnote to add
|
||||||
*/
|
|
||||||
public void setFootnotes(CTFootnotes footnotes) {
|
|
||||||
ctFootnotes = footnotes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add an XWPFFootnote to the document
|
|
||||||
*
|
|
||||||
* @param footnote
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void addFootnote(XWPFFootnote footnote) {
|
public void addFootnote(XWPFFootnote footnote) {
|
||||||
@ -135,11 +152,12 @@ public class XWPFFootnotes extends POIXMLDocumentPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add a footnote to the document
|
* Add a CT footnote to the document
|
||||||
*
|
*
|
||||||
* @param note
|
* @param note CTFtnEdn to add.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@Internal
|
||||||
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
||||||
CTFtnEdn newNote = ctFootnotes.addNewFootnote();
|
CTFtnEdn newNote = ctFootnotes.addNewFootnote();
|
||||||
newNote.set(note);
|
newNote.set(note);
|
||||||
@ -149,52 +167,18 @@ public class XWPFFootnotes extends POIXMLDocumentPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
* Get the list of {@link XWPFFootnote} in the Footnotes part.
|
||||||
*/
|
|
||||||
public XWPFDocument getXWPFDocument() {
|
|
||||||
if (document != null) {
|
|
||||||
return document;
|
|
||||||
} else {
|
|
||||||
return (XWPFDocument) getParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setXWPFDocument(XWPFDocument doc) {
|
|
||||||
document = doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new footnote and add it to the document.
|
|
||||||
* <p>The new note will have one paragraph with the style "FootnoteText"
|
|
||||||
* and one run containing the required footnote reference with the
|
|
||||||
* style "FootnoteReference".
|
|
||||||
* </p>
|
|
||||||
* @return New XWPFFootnote
|
|
||||||
*/
|
|
||||||
public XWPFFootnote createFootnote() {
|
|
||||||
CTFtnEdn newNote = CTFtnEdn.Factory.newInstance();
|
|
||||||
newNote.setType(STFtnEdn.NORMAL);
|
|
||||||
|
|
||||||
XWPFFootnote footnote = addFootnote(newNote);
|
|
||||||
int id = ctFootnotes.sizeOfFootnoteArray();
|
|
||||||
footnote.getCTFtnEdn().setId(BigInteger.valueOf(id));
|
|
||||||
return footnote;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified footnote if present.
|
|
||||||
*
|
*
|
||||||
* @param pos
|
* @return List, possibly empty, of footnotes.
|
||||||
* @return True if the footnote was removed.
|
|
||||||
*/
|
*/
|
||||||
public boolean removeFootnote(int pos) {
|
public List<XWPFFootnote> getFootnotesList() {
|
||||||
if (ctFootnotes.sizeOfFootnoteArray() >= pos - 1) {
|
List<XWPFFootnote> resultList = new ArrayList<XWPFFootnote>();
|
||||||
ctFootnotes.removeFootnote(pos);
|
for (AbstractXWPFFootnoteEndnote note : listFootnote) {
|
||||||
listFootnote.remove(pos);
|
resultList.add((XWPFFootnote)note);
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,21 +76,24 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para
|
|||||||
if (o instanceof CTFtnEdnRef) {
|
if (o instanceof CTFtnEdnRef) {
|
||||||
CTFtnEdnRef ftn = (CTFtnEdnRef) o;
|
CTFtnEdnRef ftn = (CTFtnEdnRef) o;
|
||||||
footnoteText.append(" [").append(ftn.getId()).append(": ");
|
footnoteText.append(" [").append(ftn.getId()).append(": ");
|
||||||
XWPFFootnote footnote =
|
AbstractXWPFFootnoteEndnote footnote =
|
||||||
ftn.getDomNode().getLocalName().equals("footnoteReference") ?
|
ftn.getDomNode().getLocalName().equals("footnoteReference") ?
|
||||||
document.getFootnoteByID(ftn.getId().intValue()) :
|
document.getFootnoteByID(ftn.getId().intValue()) :
|
||||||
document.getEndnoteByID(ftn.getId().intValue());
|
document.getEndnoteByID(ftn.getId().intValue());
|
||||||
|
if (null != footnote) {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (XWPFParagraph p : footnote.getParagraphs()) {
|
for (XWPFParagraph p : footnote.getParagraphs()) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
footnoteText.append("\n");
|
footnoteText.append("\n");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
footnoteText.append(p.getText());
|
||||||
}
|
}
|
||||||
first = false;
|
} else {
|
||||||
footnoteText.append(p.getText());
|
footnoteText.append("!!! End note with ID \"" + ftn.getId() + "\" not found in document.");
|
||||||
}
|
}
|
||||||
|
|
||||||
footnoteText.append("] ");
|
footnoteText.append("] ");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.dispose();
|
c.dispose();
|
||||||
@ -1674,11 +1677,16 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para
|
|||||||
* The footnote reference run will have the style name "FootnoteReference".
|
* The footnote reference run will have the style name "FootnoteReference".
|
||||||
*
|
*
|
||||||
* @param footnote Footnote to which to add a reference.
|
* @param footnote Footnote to which to add a reference.
|
||||||
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public void addFootnoteReference(XWPFFootnote footnote) {
|
public void addFootnoteReference(AbstractXWPFFootnoteEndnote footnote) {
|
||||||
XWPFRun run = createRun();
|
XWPFRun run = createRun();
|
||||||
CTR ctRun = run.getCTR();
|
CTR ctRun = run.getCTR();
|
||||||
ctRun.addNewRPr().addNewRStyle().setVal("FootnoteReference");
|
ctRun.addNewRPr().addNewRStyle().setVal("FootnoteReference");
|
||||||
ctRun.addNewFootnoteReference().setId(footnote.getId());
|
if (footnote instanceof XWPFEndnote) {
|
||||||
|
ctRun.addNewEndnoteReference().setId(footnote.getId());
|
||||||
|
} else {
|
||||||
|
ctRun.addNewFootnoteReference().setId(footnote.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,10 +147,10 @@ public final class XWPFRelation extends POIXMLRelation {
|
|||||||
XWPFFootnotes.class
|
XWPFFootnotes.class
|
||||||
);
|
);
|
||||||
public static final XWPFRelation ENDNOTE = new XWPFRelation(
|
public static final XWPFRelation ENDNOTE = new XWPFRelation(
|
||||||
null,
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml",
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
|
||||||
null,
|
"/word/endnotes.xml",
|
||||||
null
|
XWPFEndnotes.class
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* Supported image formats
|
* Supported image formats
|
||||||
|
@ -0,0 +1,160 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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 static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
||||||
|
|
||||||
|
public class TestXWPFEndnote {
|
||||||
|
|
||||||
|
private XWPFDocument docOut;
|
||||||
|
private String p1Text;
|
||||||
|
private String p2Text;
|
||||||
|
private BigInteger endnoteId;
|
||||||
|
private XWPFEndnote endnote;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
docOut = new XWPFDocument();
|
||||||
|
p1Text = "First paragraph in footnote";
|
||||||
|
p2Text = "Second paragraph in footnote";
|
||||||
|
|
||||||
|
// NOTE: XWPFDocument.createEndnote() delegates directly
|
||||||
|
// to XWPFEndnotes.createEndnote() so this tests
|
||||||
|
// both creation of new XWPFEndnotes in document
|
||||||
|
// and XWPFEndnotes.createEndnote();
|
||||||
|
|
||||||
|
// NOTE: Creating the endnote does not automatically
|
||||||
|
// create a first paragraph.
|
||||||
|
endnote = docOut.createEndnote();
|
||||||
|
endnoteId = endnote.getId();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddParagraphsToFootnote() throws IOException {
|
||||||
|
|
||||||
|
// Add a run to the first paragraph:
|
||||||
|
|
||||||
|
XWPFParagraph p1 = endnote.createParagraph();
|
||||||
|
p1.createRun().setText(p1Text);
|
||||||
|
|
||||||
|
// Create a second paragraph:
|
||||||
|
|
||||||
|
XWPFParagraph p = endnote.createParagraph();
|
||||||
|
assertNotNull("Paragraph is null", p);
|
||||||
|
p.createRun().setText(p2Text);
|
||||||
|
|
||||||
|
XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut);
|
||||||
|
|
||||||
|
XWPFEndnote testEndnote = docIn.getEndnoteByID(endnoteId.intValue());
|
||||||
|
assertNotNull(testEndnote);
|
||||||
|
|
||||||
|
assertEquals(2, testEndnote.getParagraphs().size());
|
||||||
|
XWPFParagraph testP1 = testEndnote.getParagraphs().get(0);
|
||||||
|
assertEquals(p1Text, testP1.getText());
|
||||||
|
|
||||||
|
XWPFParagraph testP2 = testEndnote.getParagraphs().get(1);
|
||||||
|
assertEquals(p2Text, testP2.getText());
|
||||||
|
|
||||||
|
// The first paragraph added using createParagraph() should
|
||||||
|
// have the required footnote reference added to the first
|
||||||
|
// run.
|
||||||
|
|
||||||
|
// Verify that we have a footnote reference in the first paragraph and not
|
||||||
|
// in the second paragraph.
|
||||||
|
|
||||||
|
XWPFRun r1 = testP1.getRuns().get(0);
|
||||||
|
assertNotNull(r1);
|
||||||
|
assertTrue("No endnote reference in testP1", r1.getCTR().getEndnoteRefList().size() > 0);
|
||||||
|
assertNotNull("No endnote reference in testP1", r1.getCTR().getEndnoteRefArray(0));
|
||||||
|
|
||||||
|
XWPFRun r2 = testP2.getRuns().get(0);
|
||||||
|
assertNotNull("Expected a run in testP2", r2);
|
||||||
|
assertTrue("Found an endnote reference in testP2", r2.getCTR().getEndnoteRefList().size() == 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddTableToFootnote() throws IOException {
|
||||||
|
XWPFTable table = endnote.createTable();
|
||||||
|
assertNotNull(table);
|
||||||
|
|
||||||
|
XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut);
|
||||||
|
|
||||||
|
XWPFEndnote testFootnote = docIn.getEndnoteByID(endnoteId.intValue());
|
||||||
|
XWPFTable testTable = testFootnote.getTableArray(0);
|
||||||
|
assertNotNull(testTable);
|
||||||
|
|
||||||
|
table = endnote.createTable(2, 3);
|
||||||
|
assertEquals(2, table.getNumberOfRows());
|
||||||
|
assertEquals(3, table.getRow(0).getTableCells().size());
|
||||||
|
|
||||||
|
// If the table is the first body element of the footnote then
|
||||||
|
// a paragraph with the footnote reference should have been
|
||||||
|
// added automatically.
|
||||||
|
|
||||||
|
assertEquals("Expected 3 body elements", 3, endnote.getBodyElements().size());
|
||||||
|
IBodyElement testP1 = endnote.getBodyElements().get(0);
|
||||||
|
assertTrue("Expected a paragraph, got " + testP1.getClass().getSimpleName() , testP1 instanceof XWPFParagraph);
|
||||||
|
XWPFRun r1 = ((XWPFParagraph)testP1).getRuns().get(0);
|
||||||
|
assertNotNull(r1);
|
||||||
|
assertTrue("No footnote reference in testP1", r1.getCTR().getEndnoteRefList().size() > 0);
|
||||||
|
assertNotNull("No footnote reference in testP1", r1.getCTR().getEndnoteRefArray(0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveEndnote() {
|
||||||
|
// NOTE: XWPFDocument.removeEndnote() delegates directly to
|
||||||
|
// XWPFEndnotes.
|
||||||
|
docOut.createEndnote();
|
||||||
|
assertEquals("Expected 2 endnotes", 2, docOut.getEndnotes().size());
|
||||||
|
assertNotNull("Didn't get second endnote", docOut.getEndnotes().get(1));
|
||||||
|
boolean result = docOut.removeEndnote(0);
|
||||||
|
assertTrue("Remove endnote did not return true", result);
|
||||||
|
assertEquals("Expected 1 endnote after removal", 1, docOut.getEndnotes().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddFootnoteRefToParagraph() {
|
||||||
|
XWPFParagraph p = docOut.createParagraph();
|
||||||
|
List<XWPFRun> runs = p.getRuns();
|
||||||
|
assertEquals("Expected no runs in new paragraph", 0, runs.size());
|
||||||
|
p.addFootnoteReference(endnote);
|
||||||
|
XWPFRun run = p.getRuns().get(0);
|
||||||
|
CTR ctr = run.getCTR();
|
||||||
|
assertNotNull("Expected a run", run);
|
||||||
|
List<CTFtnEdnRef> endnoteRefList = ctr.getEndnoteReferenceList();
|
||||||
|
assertNotNull(endnoteRefList);
|
||||||
|
CTFtnEdnRef ref = endnoteRefList.get(0);
|
||||||
|
assertNotNull(ref);
|
||||||
|
assertEquals("Endnote ID and reference ID did not match", endnote.getId(), ref.getId());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.math.BigInteger;
|
||||||
|
|
||||||
|
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class TestXWPFEndnotes extends TestCase {
|
||||||
|
|
||||||
|
public void testCreateEndnotes() throws IOException{
|
||||||
|
XWPFDocument docOut = new XWPFDocument();
|
||||||
|
|
||||||
|
XWPFEndnotes footnotes = docOut.createEndnotes();
|
||||||
|
|
||||||
|
assertNotNull(footnotes);
|
||||||
|
|
||||||
|
XWPFEndnotes secondFootnotes = docOut.createEndnotes();
|
||||||
|
|
||||||
|
assertSame(footnotes, secondFootnotes);
|
||||||
|
|
||||||
|
docOut.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddEndnotesToDocument() throws IOException {
|
||||||
|
XWPFDocument docOut = new XWPFDocument();
|
||||||
|
|
||||||
|
// NOTE: XWPFDocument.createEndnote() delegates directly
|
||||||
|
// to XWPFFootnotes.createEndnote() so this tests
|
||||||
|
// both creation of new XWPFFootnotes in document
|
||||||
|
// and XWPFFootnotes.createEndnote();
|
||||||
|
XWPFEndnote endnote = docOut.createEndnote();
|
||||||
|
BigInteger noteId = endnote.getId();
|
||||||
|
|
||||||
|
XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut);
|
||||||
|
|
||||||
|
XWPFEndnote note = docIn.getEndnoteByID(noteId.intValue());
|
||||||
|
assertNotNull(note);
|
||||||
|
assertEquals(STFtnEdn.NORMAL, note.getCTFtnEdn().getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -150,9 +150,11 @@ public class TestXWPFFootnote {
|
|||||||
assertNotNull("Expected a run", run);
|
assertNotNull("Expected a run", run);
|
||||||
CTFtnEdnRef ref = ctr.getFootnoteReferenceList().get(0);
|
CTFtnEdnRef ref = ctr.getFootnoteReferenceList().get(0);
|
||||||
assertNotNull(ref);
|
assertNotNull(ref);
|
||||||
|
// FIXME: Verify that the footnote reference is w:endnoteReference, not w:footnoteReference
|
||||||
assertEquals("Footnote ID and reference ID did not match", footnote.getId(), ref.getId());
|
assertEquals("Footnote ID and reference ID did not match", footnote.getId(), ref.getId());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,11 @@ public class TestXWPFFootnotes extends TestCase {
|
|||||||
public void testCreateFootnotes() throws IOException{
|
public void testCreateFootnotes() throws IOException{
|
||||||
XWPFDocument docOut = new XWPFDocument();
|
XWPFDocument docOut = new XWPFDocument();
|
||||||
|
|
||||||
XWPFFootnotes footnotes = docOut.createFootnotes();
|
AbstractXWPFFootnotesEndnotes footnotes = docOut.createFootnotes();
|
||||||
|
|
||||||
assertNotNull(footnotes);
|
assertNotNull(footnotes);
|
||||||
|
|
||||||
XWPFFootnotes secondFootnotes = docOut.createFootnotes();
|
AbstractXWPFFootnotesEndnotes secondFootnotes = docOut.createFootnotes();
|
||||||
|
|
||||||
assertSame(footnotes, secondFootnotes);
|
assertSame(footnotes, secondFootnotes);
|
||||||
|
|
||||||
|
@ -17,17 +17,15 @@
|
|||||||
|
|
||||||
package org.apache.poi.xwpf.usermodel;
|
package org.apache.poi.xwpf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.POITestCase.assertContains;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.apache.poi.POITestCase.assertContains;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public final class TestXWPFSDT {
|
public final class TestXWPFSDT {
|
||||||
@ -168,8 +166,8 @@ public final class TestXWPFSDT {
|
|||||||
for (XWPFFootnote footnote : doc.getFootnotes()) {
|
for (XWPFFootnote footnote : doc.getFootnotes()) {
|
||||||
sdts.addAll(extractSDTsFromBodyElements(footnote.getBodyElements()));
|
sdts.addAll(extractSDTsFromBodyElements(footnote.getBodyElements()));
|
||||||
}
|
}
|
||||||
for (Map.Entry<Integer, XWPFFootnote> e : doc.endnotes.entrySet()) {
|
for (XWPFEndnote footnote : doc.getEndnotes()) {
|
||||||
sdts.addAll(extractSDTsFromBodyElements(e.getValue().getBodyElements()));
|
sdts.addAll(extractSDTsFromBodyElements(footnote.getBodyElements()));
|
||||||
}
|
}
|
||||||
return sdts;
|
return sdts;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user