/* ==================================================================== | |
/* ==================================================================== | |
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.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.List; | |
import org.apache.poi.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.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; | |
public class XWPFFootnote implements Iterable<XWPFParagraph>, IBody { | |
private List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>(); | |
private List<XWPFTable> tables = new ArrayList<XWPFTable>(); | |
private List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>(); | |
private List<IBodyElement> bodyElements = new ArrayList<IBodyElement>(); | |
private CTFtnEdn ctFtnEdn; | |
private XWPFFootnotes footnotes; | |
private XWPFDocument document; | |
public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) { | |
footnotes = xFootnotes; | |
ctFtnEdn = note; | |
document = xFootnotes.getXWPFDocument(); | |
init(); | |
} | |
public XWPFFootnote(XWPFDocument document, CTFtnEdn body) { | |
ctFtnEdn = 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(); | |
} | |
public List<XWPFParagraph> getParagraphs() { | |
return paragraphs; | |
} | |
public Iterator<XWPFParagraph> iterator() { | |
return paragraphs.iterator(); | |
} | |
public List<XWPFTable> getTables() { | |
return tables; | |
} | |
public List<XWPFPictureData> getPictures() { | |
return pictures; | |
} | |
public List<IBodyElement> getBodyElements() { | |
return bodyElements; | |
} | |
public CTFtnEdn getCTFtnEdn() { | |
return ctFtnEdn; | |
} | |
public void setCTFtnEdn(CTFtnEdn footnote) { | |
ctFtnEdn = footnote; | |
} | |
/** | |
* @param pos in table array | |
* @return The 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 XWPFTable to the arrays bodyElements and tables | |
* | |
* @param pos | |
* @param table | |
* @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.getTblArray()) { | |
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 | |
* if there is no corresponding {@link XWPFTable} the method will return null | |
* | |
* @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 ctTable in the paragraphList of this header or footer | |
* the method will return this paragraph | |
* if there is no corresponding {@link XWPFParagraph} the method will return null | |
* | |
* @param p is instance of CTP and is searching for an XWPFParagraph | |
* @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer | |
* XWPFParagraph with the correspondig CTP p | |
* @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 paragraph that holds | |
* the text of the header or footer. | |
* | |
* @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 TableCell which belongs to the TableCell | |
* | |
* @param cell | |
* @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 | |
*/ | |
private boolean isCursorInFtn(XmlCursor cursor) { | |
XmlCursor verify = cursor.newCursor(); | |
verify.toParent(); | |
if (verify.getObject() == this.ctFtnEdn) { | |
return true; | |
} | |
return false; | |
} | |
public POIXMLDocumentPart getOwner() { | |
return footnotes; | |
} | |
/** | |
* @param cursor | |
* @return the inserted table | |
* @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 paragraph at position of the cursor | |
* | |
* @param cursor | |
* @return the inserted paragraph | |
* @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)) || (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 table to the end of the footnote | |
* | |
* @param table | |
* @return the added 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 paragraph to the end of the footnote | |
* | |
* @param paragraph | |
* @return the added XWPFParagraph | |
*/ | |
public XWPFParagraph addNewParagraph(CTP paragraph) { | |
CTP newPara = ctFtnEdn.addNewP(); | |
newPara.set(paragraph); | |
XWPFParagraph xPara = new XWPFParagraph(newPara, this); | |
paragraphs.add(xPara); | |
return xPara; | |
} | |
/** | |
* @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument() | |
*/ | |
public XWPFDocument getXWPFDocument() { | |
return document; | |
} | |
/** | |
* returns the Part, to which the body belongs, which you need for adding relationship to other parts | |
* | |
* @see org.apache.poi.xwpf.usermodel.IBody#getPart() | |
*/ | |
public POIXMLDocumentPart getPart() { | |
return footnotes; | |
} | |
/** | |
* get the PartType of the body | |
* | |
* @see org.apache.poi.xwpf.usermodel.IBody#getPartType() | |
*/ | |
public BodyType getPartType() { | |
return BodyType.FOOTNOTE; | |
} | |
} |