blob: 801f2106a7e4e7d398b8f8ee762d6c31404c9c64 [file] [log] [blame]
/************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
*
* Use is subject to license terms.
*
* Licensed 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. You can also
* obtain a copy of the License at http://odftoolkit.org/docs/license.txt
*
* 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.odftoolkit.simple;
import java.awt.Rectangle;
import java.io.File;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.odftoolkit.odfdom.dom.OdfContentDom;
import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.odftoolkit.odfdom.dom.attribute.text.TextAnchorTypeAttribute;
import org.odftoolkit.odfdom.dom.element.draw.DrawControlElement;
import org.odftoolkit.odfdom.dom.element.draw.DrawFrameElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeDocumentStylesElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeFormsElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeMasterStylesElement;
import org.odftoolkit.odfdom.dom.element.office.OfficeTextElement;
import org.odftoolkit.odfdom.dom.element.style.StyleColumnsElement;
import org.odftoolkit.odfdom.dom.element.style.StyleFooterElement;
import org.odftoolkit.odfdom.dom.element.style.StyleHeaderElement;
import org.odftoolkit.odfdom.dom.element.style.StyleMasterPageElement;
import org.odftoolkit.odfdom.dom.element.style.StylePageLayoutPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleSectionPropertiesElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexBodyElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexEntryLinkStartElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexEntryTabStopElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexSourceStylesElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexTitleElement;
import org.odftoolkit.odfdom.dom.element.text.TextIndexTitleTemplateElement;
import org.odftoolkit.odfdom.dom.element.text.TextPElement;
import org.odftoolkit.odfdom.dom.element.text.TextParagraphElementBase;
import org.odftoolkit.odfdom.dom.element.text.TextSectionElement;
import org.odftoolkit.odfdom.dom.element.text.TextSequenceDeclsElement;
import org.odftoolkit.odfdom.dom.element.text.TextTableOfContentElement;
import org.odftoolkit.odfdom.dom.element.text.TextTableOfContentEntryTemplateElement;
import org.odftoolkit.odfdom.dom.element.text.TextTableOfContentSourceElement;
import org.odftoolkit.odfdom.dom.element.text.TextTocMarkElement;
import org.odftoolkit.odfdom.dom.element.text.TextTocMarkStartElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeAutomaticStyles;
import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeMasterStyles;
import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeStyles;
import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle;
import org.odftoolkit.odfdom.incubator.doc.style.OdfStylePageLayout;
import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph;
import org.odftoolkit.odfdom.pkg.MediaType;
import org.odftoolkit.odfdom.pkg.OdfElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.pkg.OdfPackage;
import org.odftoolkit.odfdom.type.CellRangeAddressList;
import org.odftoolkit.odfdom.type.Length.Unit;
import org.odftoolkit.simple.chart.AbstractChartContainer;
import org.odftoolkit.simple.chart.Chart;
import org.odftoolkit.simple.chart.ChartContainer;
import org.odftoolkit.simple.chart.DataSet;
import org.odftoolkit.simple.common.field.AbstractVariableContainer;
import org.odftoolkit.simple.common.field.VariableContainer;
import org.odftoolkit.simple.common.field.VariableField;
import org.odftoolkit.simple.common.field.VariableField.VariableType;
import org.odftoolkit.simple.draw.Control;
import org.odftoolkit.simple.draw.ControlContainer;
import org.odftoolkit.simple.form.AbstractFormContainer;
import org.odftoolkit.simple.form.Form;
import org.odftoolkit.simple.form.FormContainer;
import org.odftoolkit.simple.style.MasterPage;
import org.odftoolkit.simple.style.TOCStyle;
import org.odftoolkit.simple.table.Table;
import org.odftoolkit.simple.text.AbstractParagraphContainer;
import org.odftoolkit.simple.text.Footer;
import org.odftoolkit.simple.text.Header;
import org.odftoolkit.simple.text.Paragraph;
import org.odftoolkit.simple.text.ParagraphContainer;
import org.odftoolkit.simple.text.Section;
import org.odftoolkit.simple.text.list.AbstractListContainer;
import org.odftoolkit.simple.text.list.List;
import org.odftoolkit.simple.text.list.ListContainer;
import org.odftoolkit.simple.text.list.ListDecorator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* This class represents an empty ODF text document.
*
*/
public class TextDocument extends Document implements ListContainer,
ParagraphContainer, VariableContainer, ChartContainer, FormContainer,
ControlContainer {
private static final String EMPTY_TEXT_DOCUMENT_PATH = "/OdfTextDocument.odt";
static final Resource EMPTY_TEXT_DOCUMENT_RESOURCE = new Resource(EMPTY_TEXT_DOCUMENT_PATH);
private ListContainerImpl listContainerImpl;
private ParagraphContainerImpl paragraphContainerImpl;
private VariableContainerImpl variableContainerImpl;
private ChartContainerImpl chartContainerImpl;
private FormContainerImpl formContainerImpl = null;
private Header firstPageHeader;
private Header standardHeader;
private Footer firstPageFooter;
private Footer standardFooter;
/**
* This enum contains all possible media types of SpreadsheetDocument
* documents.
*/
public enum OdfMediaType implements MediaType {
TEXT(Document.OdfMediaType.TEXT), TEXT_TEMPLATE(Document.OdfMediaType.TEXT_TEMPLATE), TEXT_MASTER(
Document.OdfMediaType.TEXT_MASTER), TEXT_WEB(Document.OdfMediaType.TEXT_WEB);
private final Document.OdfMediaType mMediaType;
OdfMediaType(Document.OdfMediaType mediaType) {
this.mMediaType = mediaType;
}
/**
* @return the mediatype of this document
*/
public String getMediaTypeString() {
return mMediaType.getMediaTypeString();
}
/**
* @return the ODF filesuffix of this document
*/
public String getSuffix() {
return mMediaType.getSuffix();
}
/**
*
* @param mediaType
* string defining an ODF document
* @return the according OdfMediatype encapuslating the given string and
* the suffix
*/
public static Document.OdfMediaType getOdfMediaType(String mediaType) {
return Document.OdfMediaType.getOdfMediaType(mediaType);
}
}
/**
* Creates an empty text document.
*
* @return ODF text document based on a default template
* @throws java.lang.Exception
* - if the document could not be created
*/
public static TextDocument newTextDocument() throws Exception {
return (TextDocument) Document.loadTemplate(EMPTY_TEXT_DOCUMENT_RESOURCE, Document.OdfMediaType.TEXT);
}
/**
* Creates an empty text document.
*
* @return ODF text document based on a default template
* @throws java.lang.Exception
* - if the document could not be created
*/
public static TextDocument newTextDocument(TextDocument.OdfMediaType mimeType) throws Exception {
return (TextDocument) Document.loadTemplate(EMPTY_TEXT_DOCUMENT_RESOURCE, Document.OdfMediaType.TEXT);
}
/**
* Creates an empty text template.
*
* @return ODF text template based on a default
* @throws java.lang.Exception
* - if the template could not be created
*/
public static TextDocument newTextTemplateDocument() throws Exception {
return (TextDocument) Document.loadTemplate(EMPTY_TEXT_DOCUMENT_RESOURCE, Document.OdfMediaType.TEXT_TEMPLATE);
}
/**
* Creates an empty text master document.
*
* @return ODF text master based on a default
* @throws java.lang.Exception
* - if the document could not be created
*/
public static TextDocument newTextMasterDocument() throws Exception {
TextDocument doc = (TextDocument) Document.loadTemplate(EMPTY_TEXT_DOCUMENT_RESOURCE,
Document.OdfMediaType.TEXT_MASTER);
doc.changeMode(OdfMediaType.TEXT_MASTER);
return doc;
}
/**
* Creates an empty text web.
*
* @return ODF text web based on a default
* @throws java.lang.Exception
* - if the document could not be created
*/
public static TextDocument newTextWebDocument() throws Exception {
TextDocument doc = (TextDocument) Document.loadTemplate(EMPTY_TEXT_DOCUMENT_RESOURCE,
Document.OdfMediaType.TEXT_WEB);
doc.changeMode(OdfMediaType.TEXT_WEB);
return doc;
}
/**
* Creates an TextDocument from the OpenDocument provided by a resource
* Stream.
*
* <p>
* Since an InputStream does not provide the arbitrary (non sequentiell)
* read access needed by TextDocument, the InputStream is cached. This
* usually takes more time compared to the other createInternalDocument
* methods. An advantage of caching is that there are no problems
* overwriting an input file.
* </p>
*
* <p>
* If the resource stream is not a ODF text document, ClassCastException
* might be thrown.
* </p>
*
* @param inputStream
* - the InputStream of the ODF text document.
* @return the text document created from the given InputStream
* @throws java.lang.Exception
* - if the document could not be created.
*/
public static TextDocument loadDocument(InputStream inputStream) throws Exception {
return (TextDocument) Document.loadDocument(inputStream);
}
/**
* Loads an TextDocument from the provided path.
*
* <p>
* TextDocument relies on the file being available for read access over the
* whole lifecycle of TextDocument.
* </p>
*
* <p>
* If the resource stream is not a ODF text document, ClassCastException
* might be thrown.
* </p>
*
* @param documentPath
* - the path from where the document can be loaded
* @return the text document from the given path or NULL if the media type
* is not supported by SIMPLE.
* @throws java.lang.Exception
* - if the document could not be created.
*/
public static TextDocument loadDocument(String documentPath) throws Exception {
return (TextDocument) Document.loadDocument(documentPath);
}
/**
* Creates an TextDocument from the OpenDocument provided by a File.
*
* <p>
* TextDocument relies on the file being available for read access over the
* whole lifecycle of TextDocument.
* </p>
*
* <p>
* If the resource stream is not a ODF text document, ClassCastException
* might be thrown.
* </p>
*
* @param file
* - a file representing the ODF text document.
* @return the text document created from the given File
* @throws java.lang.Exception
* - if the document could not be created.
*/
public static TextDocument loadDocument(File file) throws Exception {
return (TextDocument) Document.loadDocument(file);
}
/**
* To avoid data duplication a new document is only created, if not already
* opened. A document is cached by this constructor using the internalpath
* as key.
*/
protected TextDocument(OdfPackage pkg, String internalPath, TextDocument.OdfMediaType odfMediaType) {
super(pkg, internalPath, odfMediaType.mMediaType);
}
/**
* Get the content root of a text document. Start here to get or create new
* elements of a text document like paragraphs, headings, tables or lists.
*
* @return content root, representing the office:text tag
* @throws Exception
* if the file DOM could not be created.
*/
@Override
public OfficeTextElement getContentRoot() throws Exception {
return super.getContentRoot(OfficeTextElement.class);
}
/**
* Creates a new paragraph and append text
*
* @param text
* @return the new paragraph
* @throws Exception
* if the file DOM could not be created.
* @deprecated As of Simple version 0.5, replaced by
* <code>addParagraph(String text)</code>
* @see #addParagraph(String)
*/
public OdfTextParagraph newParagraph(String text) throws Exception {
OdfTextParagraph para = newParagraph();
para.addContent(text);
return para;
}
/**
* Creates a new paragraph
*
* @return The new paragraph
* @throws Exception
* if the file DOM could not be created.
* @deprecated As of Simple version 0.5, replaced by
* <code>Paragraph.newParagraph(ParagraphContainer)</code>
* @see Paragraph#newParagraph(ParagraphContainer)
* @see #addParagraph(String)
*/
public OdfTextParagraph newParagraph() throws Exception {
OfficeTextElement odfText = getContentRoot();
return (OdfTextParagraph) odfText.newTextPElement();
}
/**
* Append text to the end of a text document. If there is no paragraph at
* the end of a document, a new one will be created.
*
* @param text
* initial text for the paragraph.
* @return The paragraph at the end of the text document, where the text has
* been added to.
* @throws Exception
* if the file DOM could not be created.
* @deprecated As of Simple version 0.5, replaced by
* <code>Paragraph.appendTextContent(String content)</code>
* @see Paragraph#appendTextContent(String)
* @see Paragraph#appendTextContentNotCollapsed(String)
* @see #getParagraphByIndex(int, boolean)
* @see #getParagraphByReverseIndex(int, boolean)
*/
public OdfTextParagraph addText(String text) throws Exception {
OfficeTextElement odfText = getContentRoot();
Node n = odfText.getLastChild();
OdfTextParagraph para;
if (OdfTextParagraph.class.isInstance(n)) {
para = (OdfTextParagraph) n;
} else {
para = newParagraph();
}
para.addContent(text);
return para;
}
/**
* Changes the document to the given mediatype. This method can only be used
* to convert a document to a related mediatype, e.g. template.
*
* @param mediaType
* the related ODF mimetype
*/
public void changeMode(OdfMediaType mediaType) {
setOdfMediaType(mediaType.mMediaType);
}
/**
* Copy a section and append it at the end of the text document, whether the
* section is in this document or in a different document.
* <p>
* The IDs and names in this section would be changed to ensure unique.
* <p>
* If the section contains a linked resource, <code>isResourceCopied</code>
* would specify whether the linked resource would be copied or not, when
* the copy and append happens within a same document.
*
* @param section
* - the section object
* @param isResourceCopied
* - whether the linked resource is copied or not.
*/
public Section appendSection(Section section, boolean isResourceCopied) {
boolean isForeignNode = false;
try {
if (section.getOdfElement().getOwnerDocument() != getContentDom())
isForeignNode = true;
TextSectionElement oldSectionEle = section.getOdfElement();
TextSectionElement newSectionEle = (TextSectionElement) oldSectionEle.cloneNode(true);
if (isResourceCopied || isForeignNode)
copyLinkedRefInBatch(newSectionEle, section.getOwnerDocument());
if (isForeignNode)
copyForeignStyleRef(newSectionEle, section.getOwnerDocument());
if (isForeignNode) // not in a same document
newSectionEle = (TextSectionElement) cloneForeignElement(newSectionEle, getContentDom(), true);
updateNames(newSectionEle);
updateXMLIds(newSectionEle);
OfficeTextElement contentRoot = getContentRoot();
contentRoot.appendChild(newSectionEle);
return Section.getInstance(newSectionEle);
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return null;
}
/**
* Create an empty section and append it at the end of the text document.
*
* @param name
* - specify the section name
* @return an instance of the section
* @throws RuntimeException
* if content DOM could not be initialized
*/
public Section appendSection(String name) {
TextSectionElement newSectionEle = null;
try {
OdfContentDom contentDocument = getContentDom();
OdfOfficeAutomaticStyles styles = contentDocument
.getAutomaticStyles();
OdfStyle style = styles.newStyle(OdfStyleFamily.Section);
StyleSectionPropertiesElement sProperties = style
.newStyleSectionPropertiesElement();
sProperties.setTextDontBalanceTextColumnsAttribute(false);
sProperties.setStyleEditableAttribute(false);
StyleColumnsElement columnEle = sProperties
.newStyleColumnsElement(1);
columnEle.setFoColumnGapAttribute("0in");
newSectionEle = getContentRoot()
.newTextSectionElement("true", name);
newSectionEle.setStyleName(style.getStyleNameAttribute());
return Section.getInstance(newSectionEle);
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
null, e);
throw new RuntimeException(name + "Section appends failed.", e);
}
}
/**
* Get the Standard Page header of this text document.
*
* @return the Standard Page header of this text document.
* @since 0.4.5
*/
public Header getHeader() {
return getHeader(false);
}
/**
* Get the header of this text document.
*
* @param isFirstPage
* if <code>isFirstPage</code> is true, return the First Page
* header, otherwise return Standard Page header.
*
* @return the header of this text document.
* @since 0.5
*/
public Header getHeader(boolean isFirstPage) {
Header tmpHeader = isFirstPage ? firstPageHeader : standardHeader;
if (tmpHeader == null) {
try {
StyleMasterPageElement masterPageElement = getMasterPage(isFirstPage);
StyleHeaderElement headerElement = OdfElement.findFirstChildNode(StyleHeaderElement.class,
masterPageElement);
if (headerElement == null) {
headerElement = masterPageElement.newStyleHeaderElement();
}
tmpHeader = new Header(headerElement);
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
if (isFirstPage) {
firstPageHeader = tmpHeader;
} else {
standardHeader = tmpHeader;
}
}
return tmpHeader;
}
/**
* Get the Standard Page footer of this text document.
*
* @return the Standard Page footer of this text document.
* @since 0.4.5
*/
public Footer getFooter() {
return getFooter(false);
}
/**
* Get the footer of this text document.
*
* @param isFirstPage
* if <code>isFirstPage</code> is true, return the First Page
* footer, otherwise return Standard Page footer.
*
* @return the footer of this text document.
* @since 0.5
*/
public Footer getFooter(boolean isFirstPage) {
Footer tmpFooter = isFirstPage ? firstPageFooter : standardFooter;
if (tmpFooter == null) {
try {
StyleMasterPageElement masterPageElement = getMasterPage(isFirstPage);
StyleFooterElement footerElement = OdfElement.findFirstChildNode(StyleFooterElement.class,
masterPageElement);
if (footerElement == null) {
footerElement = masterPageElement.newStyleFooterElement();
}
tmpFooter = new Footer(footerElement);
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
if (isFirstPage) {
firstPageFooter = tmpFooter;
} else {
standardFooter = tmpFooter;
}
}
return tmpFooter;
}
public OdfElement getTableContainerElement() {
return getTableContainerImpl().getTableContainerElement();
}
public OdfElement getListContainerElement() {
return getListContainerImpl().getListContainerElement();
}
public List addList() {
return getListContainerImpl().addList();
}
public List addList(ListDecorator decorator) {
return getListContainerImpl().addList(decorator);
}
public void clearList() {
getListContainerImpl().clearList();
}
public Iterator<List> getListIterator() {
return getListContainerImpl().getListIterator();
}
public boolean removeList(List list) {
return getListContainerImpl().removeList(list);
}
/**
* Appends a new page break to this document.
*
* @since 0.6.5
*/
public void addPageBreak() {
addPageOrColumnBreak(null, "page");
}
/**
* Appends a new page break to this document after the reference paragraph.
*
* @param refParagraph
* the reference paragraph after where the page break inserted.
* @since 0.6.5
*/
public void addPageBreak(Paragraph refParagraph) {
addPageOrColumnBreak(refParagraph, "page");
}
/**
* Defines several columns to the page whose style is specified.
*
* @param columnsNumber
* the number of columns (are of width identical)
* @param spacing
* column spacing in cm (ex. 2.40 for 2,4 cm)
*
* @since 0.6.6
*/
public void setPageColumns(int columnsNumber, double spacing) {
String vSpacingColumn = (new DecimalFormat("#0.###").format(spacing) + Unit.CENTIMETER.abbr()).replace(",", ".");
// Get back the name of the style Page wanted Layout
// (Example of the got back name : pm1 or Mpm1 for the standard style)
try {
String stylePageLayoutName = null;
int pageLayoutNameCount = 0;
NodeList list = getStylesDom().getElementsByTagName("office:master-styles");
if (list.getLength() > 0) {
OdfOfficeMasterStyles officeMasterStyles = (OdfOfficeMasterStyles) list.item(0);
// Get back the StylePageLayoutName
for (int i = 0; i < officeMasterStyles.getLength(); i++) {
StyleMasterPageElement syleMasterPage = (StyleMasterPageElement) officeMasterStyles.item(i);
if(syleMasterPage.getStyleNameAttribute().equals("Standard")){
stylePageLayoutName = syleMasterPage.getStylePageLayoutNameAttribute();
break;
}
}
// Allows to know if StylePageLayoutName is unique
for (int i = 0; i < officeMasterStyles.getLength(); i++) {
StyleMasterPageElement syleMasterPage = (StyleMasterPageElement) officeMasterStyles.item(i);
if(syleMasterPage.getStylePageLayoutNameAttribute().equals(stylePageLayoutName)){
pageLayoutNameCount++;
}
}
}
OdfOfficeAutomaticStyles autoStyles = getStylesDom().getAutomaticStyles();
int autoStylesCount = autoStyles.getLength();
OdfStylePageLayout pageLayout = autoStyles.getPageLayout(stylePageLayoutName);
if(pageLayout != null) {
// Clone the OdfStylePageLayout if another master style possesses the same name before modifying its properties
if(pageLayoutNameCount > 1){
Node pageLayoutNew = pageLayout.cloneNode(true);
// Rename the style of the clone before modifying its properties
String oldPageLayoutName = pageLayout.getStyleNameAttribute();
pageLayout.setStyleNameAttribute("Mpm" + (autoStylesCount+1));
// Allocate the new name of the style to the master style (the cloned style)
if (list.getLength() > 0) {
OdfOfficeMasterStyles masterpage = (OdfOfficeMasterStyles) list.item(0);
for (int i = 0; i < masterpage.getLength(); i++) {
StyleMasterPageElement vSyleMasterPage = (StyleMasterPageElement) masterpage.item(i);
if(vSyleMasterPage.getStyleNameAttribute().equals("Standard")){
if(vSyleMasterPage.getStylePageLayoutNameAttribute().equals(oldPageLayoutName)){
vSyleMasterPage.setStylePageLayoutNameAttribute(pageLayout.getStyleNameAttribute());
}
}
}
}
autoStyles.appendChild(pageLayoutNew);
}
NodeList vListStlePageLprop = pageLayout.getElementsByTagName("style:page-layout-properties");
StylePageLayoutPropertiesElement vStlePageLprop = (StylePageLayoutPropertiesElement) vListStlePageLprop.item(0);
StyleColumnsElement vStyleColumnsElement = vStlePageLprop.newStyleColumnsElement(columnsNumber);
vStyleColumnsElement.setFoColumnGapAttribute(vSpacingColumn);
}
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
throw new RuntimeException("Page column sets failed.", e);
}
}
/**
* Appends a new column break to this document.
*
* @since 0.6.6
*/
public void addColumnBreak() {
addPageOrColumnBreak(null, "column");
}
/**
* Appends a new column break to this document after the reference paragraph.
*
* @param refParagraph
* the reference paragraph after where the column break inserted.
* @since 0.6.6
*/
public void addColumnBreak(Paragraph refParagraph) {
addPageOrColumnBreak(refParagraph, "column");
}
/**
* Appends a new column or page break to this document.
*
* @param refParagraph
* the reference paragraph after where the column break inserted.
* @param breakAttribute
* the attribute name (page or column)
*/
private void addPageOrColumnBreak(Paragraph refParagraph, String breakAttribute) {
TextPElement pEle = null;
try {
OdfContentDom contentDocument = getContentDom();
OdfOfficeAutomaticStyles styles = contentDocument.getAutomaticStyles();
OdfStyle style = styles.newStyle(OdfStyleFamily.Paragraph);
style.newStyleParagraphPropertiesElement().setFoBreakBeforeAttribute(breakAttribute);
if(refParagraph == null){
pEle = getContentRoot().newTextPElement();
} else {
OfficeTextElement contentRoot = getContentRoot();
pEle = contentRoot.newTextPElement();
OdfElement refEle = refParagraph.getOdfElement();
contentRoot.insertBefore(pEle, refEle.getNextSibling());
}
pEle.setStyleName(style.getStyleNameAttribute());
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
throw new RuntimeException(breakAttribute + "Break appends failed.", e);
}
}
/**
* Appends a new page break to this document after the reference paragraph,
* and the master page style will be applied to the new page.
*
* @param refParagraph
* the reference paragraph after where the page break inserted.
* @param master
* the master page style applied to the new page.
* @since 0.8
*/
public void addPageBreak(Paragraph refParagraph, MasterPage master) {
TextPElement pEle = null;
try {
OdfContentDom contentDocument = getContentDom();
OdfOfficeAutomaticStyles styles = contentDocument
.getAutomaticStyles();
OdfStyle style = styles.newStyle(OdfStyleFamily.Paragraph);
style.setStyleMasterPageNameAttribute(master.getName());
if (refParagraph == null) {
pEle = getContentRoot().newTextPElement();
} else {
OfficeTextElement contentRoot = getContentRoot();
pEle = contentRoot.newTextPElement();
OdfElement refEle = refParagraph.getOdfElement();
contentRoot.insertBefore(pEle, refEle.getNextSibling());
}
pEle.setStyleName(style.getStyleNameAttribute());
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
null, e);
throw new RuntimeException("PageBreak with mater page - "
+ master.getName() + " - appends failed.", e);
}
}
/**
* Creates a new paragraph and append text.
*
* @param text
* the text content of this paragraph
* @return the new paragraph
*/
public Paragraph addParagraph(String text) {
Paragraph para = getParagraphContainerImpl().addParagraph(text);
return para;
}
/**
* Remove paragraph from this document
*
* @param para
* the instance of paragraph
* @return true if the paragraph is removed successfully, false if errors
* happen.
*/
public boolean removeParagraph(Paragraph para) {
return getParagraphContainerImpl().removeParagraph(para);
}
public OdfElement getParagraphContainerElement() {
return getParagraphContainerImpl().getParagraphContainerElement();
}
public Paragraph getParagraphByIndex(int index, boolean isEmptyParagraphSkipped) {
return getParagraphContainerImpl().getParagraphByIndex(index, isEmptyParagraphSkipped);
}
public Paragraph getParagraphByReverseIndex(int reverseIndex, boolean isEmptyParagraphSkipped) {
return getParagraphContainerImpl().getParagraphByReverseIndex(reverseIndex, isEmptyParagraphSkipped);
}
public Iterator<Paragraph> getParagraphIterator() {
return getParagraphContainerImpl().getParagraphIterator();
}
public VariableField declareVariable(String name, VariableType type) {
return getVariableContainerImpl().declareVariable(name, type);
}
public VariableField getVariableFieldByName(String name) {
return getVariableContainerImpl().getVariableFieldByName(name);
}
public OdfElement getVariableContainerElement() {
return getVariableContainerImpl().getVariableContainerElement();
}
public Chart createChart(String title, DataSet dataset, Rectangle rect) {
return getChartContainerImpl().createChart(title, dataset, rect);
}
public Chart createChart(String title, SpreadsheetDocument document, CellRangeAddressList cellRangeAddr, boolean firstRowAsLabel,
boolean firstColumnAsLabel, boolean rowAsDataSeries, Rectangle rect) {
return getChartContainerImpl().createChart(title, document, cellRangeAddr, firstRowAsLabel, firstColumnAsLabel,
rowAsDataSeries, rect);
}
public Chart createChart(String title, String[] labels, String[] legends, double[][] data, Rectangle rect) {
return getChartContainerImpl().createChart(title, labels, legends, data, rect);
}
public void deleteChartById(String chartId) {
getChartContainerImpl().deleteChartById(chartId);
}
public void deleteChartByTitle(String title) {
getChartContainerImpl().deleteChartByTitle(title);
}
public Chart getChartById(String chartId) {
return getChartContainerImpl().getChartById(chartId);
}
public java.util.List<Chart> getChartByTitle(String title) {
return getChartContainerImpl().getChartByTitle(title);
}
public int getChartCount() {
return getChartContainerImpl().getChartCount();
}
private ListContainerImpl getListContainerImpl() {
if (listContainerImpl == null) {
listContainerImpl = new ListContainerImpl();
}
return listContainerImpl;
}
private class ListContainerImpl extends AbstractListContainer {
public OdfElement getListContainerElement() {
OdfElement containerElement = null;
try {
containerElement = getContentRoot();
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return containerElement;
}
}
private StyleMasterPageElement getMasterPage(boolean pFirstPage) throws Exception {
String pageStyleName = pFirstPage ? "First_20_Page" : "Standard";
OfficeDocumentStylesElement rootElement = getStylesDom().getRootElement();
OfficeMasterStylesElement masterStyles = OdfElement.findFirstChildNode(OfficeMasterStylesElement.class,
rootElement);
if (masterStyles == null) {
masterStyles = rootElement.newOfficeMasterStylesElement();
}
StyleMasterPageElement masterPageEle = null;
NodeList lastMasterPages = masterStyles.getElementsByTagNameNS(OdfDocumentNamespace.STYLE.getUri(),
"master-page");
if (lastMasterPages != null && lastMasterPages.getLength() > 0) {
for (int i = 0; i < lastMasterPages.getLength(); i++) {
StyleMasterPageElement masterPage = (StyleMasterPageElement) lastMasterPages.item(i);
String styleName = masterPage.getStyleNameAttribute();
if (pageStyleName.equals(styleName)) {
masterPageEle = masterPage;
break;
}
}
}
if (masterPageEle == null) {
OdfStylePageLayout layout = OdfElement.findFirstChildNode(OdfStylePageLayout.class, getStylesDom()
.getAutomaticStyles());
masterPageEle = masterStyles.newStyleMasterPageElement(pageStyleName, layout.getStyleNameAttribute());
}
return masterPageEle;
}
private class ParagraphContainerImpl extends AbstractParagraphContainer {
public OdfElement getParagraphContainerElement() {
OdfElement containerElement = null;
try {
containerElement = getContentRoot();
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return containerElement;
}
}
private ParagraphContainerImpl getParagraphContainerImpl() {
if (paragraphContainerImpl == null)
paragraphContainerImpl = new ParagraphContainerImpl();
return paragraphContainerImpl;
}
private class VariableContainerImpl extends AbstractVariableContainer {
public OdfElement getVariableContainerElement() {
try {
return getContentRoot();
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
return null;
}
}
}
private VariableContainer getVariableContainerImpl() {
if (variableContainerImpl == null) {
variableContainerImpl = new VariableContainerImpl();
}
return variableContainerImpl;
}
private ChartContainerImpl getChartContainerImpl() {
if (chartContainerImpl == null) {
chartContainerImpl = new ChartContainerImpl(this);
}
return chartContainerImpl;
}
private class ChartContainerImpl extends AbstractChartContainer {
TextDocument sdoc;
protected ChartContainerImpl(Document doc) {
super(doc);
sdoc = (TextDocument) doc;
}
protected DrawFrameElement getChartFrame() throws Exception {
OdfContentDom contentDom2 = sdoc.getContentDom();
DrawFrameElement drawFrame = contentDom2.newOdfElement(DrawFrameElement.class);
TextPElement lastPara = sdoc.getContentRoot().newTextPElement();
lastPara.appendChild(drawFrame);
drawFrame.setTextAnchorTypeAttribute(TextAnchorTypeAttribute.Value.PARAGRAPH.toString());
return drawFrame;
}
}
/**
* Create a new Table Of Content to this document before the reference
* paragraph. Because until you do a full layout of the document, taking
* into account font metrics,line breaking algorithms, hyphenation, image
* positioning, "orphan and widow" rules, etc., you don't know what content
* is on which page. So all the page numbers in TOC are be set value "1".
* Please update the page numbers from AOO Menus: Tools->Update->All Indexes
* and Tables
*
* @param refParagraph
* the reference paragraph where the TOC be inserted.
* @param before
* true:insert TOC before the reference paragraph. false:insert
* TOC after the reference paragraph.
* @since 0.8.6
*/
public TextTableOfContentElement createDefaultTOC(Paragraph refParagraph, boolean before) {
TextTableOfContentElement textTableOfContent =null;
if(refParagraph==null){
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
"Failed to create Default TOC, The refParagraph where the TOC be inserted is null");
throw new RuntimeException("Failed to create Default TOC, The refParagraph where the TOC be inserted is null");
}
Node refparagraphNode = refParagraph.getOdfElement();
Node rootNode = refparagraphNode.getParentNode();
try {
OdfContentDom content = getContentDom();
textTableOfContent = content
.newOdfElement(TextTableOfContentElement.class);
textTableOfContent.setTextNameAttribute("Table of Contents");
textTableOfContent.setTextProtectedAttribute(true);
TextTableOfContentSourceElement textTableOfContentSource = textTableOfContent
.newTextTableOfContentSourceElement();
textTableOfContentSource.setTextOutlineLevelAttribute(10);
textTableOfContentSource.setTextUseIndexMarksAttribute(true);
TextIndexTitleTemplateElement textIndexTitleTemplate = textTableOfContentSource
.newTextIndexTitleTemplateElement();
textIndexTitleTemplate
.setTextStyleNameAttribute("Contents_20_Heading");
textIndexTitleTemplate.setTextContent("Table of Contents");
for (int i = 1; i <= 10; i++) {
TextTableOfContentEntryTemplateElement textTableOfContentEntryTemplate = textTableOfContentSource
.newTextTableOfContentEntryTemplateElement(i,
"Contents_20_" + i);
TextIndexEntryLinkStartElement TextIndexEntryLinkStart = textTableOfContentEntryTemplate
.newTextIndexEntryLinkStartElement();
TextIndexEntryLinkStart
.setTextStyleNameAttribute("Index_20_Link");
textTableOfContentEntryTemplate
.newTextIndexEntryChapterElement();
textTableOfContentEntryTemplate.newTextIndexEntryTextElement();
TextIndexEntryTabStopElement TextIndexEntryTabStop = textTableOfContentEntryTemplate
.newTextIndexEntryTabStopElement("right");
TextIndexEntryTabStop.setStyleLeaderCharAttribute(".");
textTableOfContentEntryTemplate
.newTextIndexEntryPageNumberElement();
textTableOfContentEntryTemplate
.newTextIndexEntryLinkEndElement();
}
TextIndexBodyElement textIndexBody = textTableOfContent
.newTextIndexBodyElement();
TextIndexTitleElement TextIndexTitle = textIndexBody
.newTextIndexTitleElement("Table of Contents_Head");
TextPElement texp = TextIndexTitle.newTextPElement();
texp.setTextStyleNameAttribute("Contents_20_Heading");
texp.setTextContent("Table of Contents");
Iterator<Paragraph> paragraphIterator = getParagraphIterator();
while (paragraphIterator.hasNext()) {
Paragraph paragraph = paragraphIterator.next();
String text = paragraph.getTextContent();
String stylename = paragraph.getStyleName();
// Outline support
if (paragraph.isHeading()) {
int headingLevel = paragraph.getHeadingLevel();
if (stylename.length() <= 0) {
stylename = "Contents_20_" + headingLevel;
}
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
// end of Outline support
// Index Makes support
TextParagraphElementBase podf = paragraph.getOdfElement();
NodeList cns = podf.getChildNodes();
for (int i = 0; i < cns.getLength(); i++) {
Node node = cns.item(i);
if (node instanceof TextTocMarkElement) {
TextTocMarkElement textTocMarkElement = (TextTocMarkElement) node;
text = textTocMarkElement.getTextStringValueAttribute();
int headingLevel = textTocMarkElement
.getTextOutlineLevelAttribute();
stylename = "Contents_20_" + headingLevel;
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
if (node instanceof TextTocMarkStartElement) {
TextTocMarkStartElement textTocMarkStartElement = (TextTocMarkStartElement) node;
Node tmp = node.getNextSibling();
while (!(tmp instanceof Text)) {
tmp = node.getNextSibling();
}
text = tmp.getTextContent();
int headingLevel = textTocMarkStartElement
.getTextOutlineLevelAttribute();
stylename = "Contents_20_" + headingLevel;
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
}
// end of Index Makes support
}
if (before) {
rootNode.insertBefore(textTableOfContent, refparagraphNode);
} else {
// Insert TOC after the refParagraph
Node refNextNode = refparagraphNode.getNextSibling();
if (refNextNode == null) {
rootNode.appendChild(textTableOfContent);
} else {
rootNode.insertBefore(textTableOfContent, refNextNode);
}
}
return textTableOfContent;
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
"Failed to create Default TOC", e);
throw new RuntimeException("Failed to create Default TOC", e);
}
}
private void ceateIndexBodyEntry(TextIndexBodyElement textIndexBody,
String stylename, String text) {
TextPElement textp = textIndexBody.newTextPElement();
textp.setTextStyleNameAttribute(stylename);
textp.newTextNode(text);
textp.newTextTabElement();
textp.newTextNode("1");
}
/**
* Create a new Table Of Content to this document before the reference
* paragraph. The additional paragraph styles list will be included in the
* TOC. Because until you do a full layout of the document, taking into
* account font metrics,line breaking algorithms, hyphenation, image
* positioning, "orphan and widow" rules, etc., you don't know what content
* is on which page. So all the page numbers in TOC are be set value "1".
* Please update the page numbers from AOO Menus: Tools->Update->All Indexes
* and Tables. If additionalStyle is null then call createDefaultTOC().
*
* @param refParagraph
* the reference paragraph before where the TOC inserted.
* @param additionalStyle
* the additional paragraph styles that you want to include in
* the TOC
* @param before
* true:insert TOC before the reference paragraph.
* false:insert TOC after the reference paragraph.
* @since 0.8.6
*/
public TextTableOfContentElement createTOCwithStyle(Paragraph refParagraph,
TOCStyle additionalStyle, boolean before) {
if(refParagraph==null){
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
"Failed to create Default TOC, The refParagraph where the TOC be inserted is null");
throw new RuntimeException("Failed to create Default TOC, The refParagraph where the TOC be inserted is null");
}
if (additionalStyle == null) {
TextTableOfContentElement textTableOfContentElement = createDefaultTOC(refParagraph, before);
return textTableOfContentElement;
}
HashMap<Integer, String> tocstyleList = additionalStyle.getStyle();
if (tocstyleList.isEmpty()) {
TextTableOfContentElement textTableOfContentElement =createDefaultTOC(refParagraph, before);
return textTableOfContentElement;
}
Collection<String> tocvalues = tocstyleList.values();
OdfOfficeStyles docstyles = getOrCreateDocumentStyles();
Iterable<OdfStyle> paragraphStyles = docstyles
.getStylesForFamily(OdfStyleFamily.Paragraph);
ArrayList<String> pstyle = new ArrayList<String>();
Iterator<OdfStyle> iterator = paragraphStyles.iterator();
while (iterator.hasNext()) {
OdfStyle style = iterator.next();
String name = style.getStyleNameAttribute();
pstyle.add(name);
}
if (!pstyle.containsAll(tocvalues)) {
Logger.getLogger(TextDocument.class.getName())
.log(Level.SEVERE,
"Failed to create TOC with Styles. Some of addtional Styles that you want to include in the TOC can't be found in the document.\n"
+ tocvalues.toString());
throw new RuntimeException(
"Failed to create TOC Styles.Some of addtional Styles that you want to include in the TOC can't be found in the document.");
}
TextTableOfContentElement textTableOfContent =null;
// Additional Styles support
HashMap<String, Integer> tmptocstyleList = new HashMap<String, Integer>();
if (!tocstyleList.isEmpty()) {
Set<Integer> key = tocstyleList.keySet();
Iterator<Integer> it = key.iterator();
while (it.hasNext()) {
Integer textOutlineLevelValue = it.next();
String textStyleNameValue = tocstyleList
.get(textOutlineLevelValue);
tmptocstyleList.put(textStyleNameValue, textOutlineLevelValue);
}
}
// end of Additional Styles support
Node refparagraphNode = refParagraph.getOdfElement();
Node rootNode = refparagraphNode.getParentNode();
try {
OdfContentDom content = getContentDom();
textTableOfContent = content
.newOdfElement(TextTableOfContentElement.class);
textTableOfContent.setTextNameAttribute("Table of Contents");
textTableOfContent.setTextProtectedAttribute(true);
TextTableOfContentSourceElement textTableOfContentSource = textTableOfContent
.newTextTableOfContentSourceElement();
textTableOfContentSource.setTextOutlineLevelAttribute(10);
textTableOfContentSource.setTextUseIndexMarksAttribute(true);
textTableOfContentSource.setTextUseIndexSourceStylesAttribute(true);
TextIndexTitleTemplateElement textIndexTitleTemplate = textTableOfContentSource
.newTextIndexTitleTemplateElement();
textIndexTitleTemplate
.setTextStyleNameAttribute("Contents_20_Heading");
textIndexTitleTemplate.setTextContent("Table of Contents");
for (int i = 1; i <= 10; i++) {
TextTableOfContentEntryTemplateElement textTableOfContentEntryTemplate = textTableOfContentSource
.newTextTableOfContentEntryTemplateElement(i,
"Contents_20_" + i);
TextIndexEntryLinkStartElement TextIndexEntryLinkStart = textTableOfContentEntryTemplate
.newTextIndexEntryLinkStartElement();
TextIndexEntryLinkStart
.setTextStyleNameAttribute("Index_20_Link");
textTableOfContentEntryTemplate
.newTextIndexEntryChapterElement();
textTableOfContentEntryTemplate.newTextIndexEntryTextElement();
TextIndexEntryTabStopElement TextIndexEntryTabStop = textTableOfContentEntryTemplate
.newTextIndexEntryTabStopElement("right");
TextIndexEntryTabStop.setStyleLeaderCharAttribute(".");
textTableOfContentEntryTemplate
.newTextIndexEntryPageNumberElement();
textTableOfContentEntryTemplate
.newTextIndexEntryLinkEndElement();
}
if (!tocstyleList.isEmpty()) {
Set<Integer> key = tocstyleList.keySet();
Iterator<Integer> it = key.iterator();
while (it.hasNext()) {
Integer textOutlineLevelValue = it.next();
String textStyleNameValue = tocstyleList
.get(textOutlineLevelValue);
TextIndexSourceStylesElement textIndexSourceStyles = textTableOfContentSource
.newTextIndexSourceStylesElement(textOutlineLevelValue);
textIndexSourceStyles
.newTextIndexSourceStyleElement(textStyleNameValue);
}
}
TextIndexBodyElement textIndexBody = textTableOfContent
.newTextIndexBodyElement();
TextIndexTitleElement TextIndexTitle = textIndexBody
.newTextIndexTitleElement("Table of Contents_Head");
TextPElement texp = TextIndexTitle.newTextPElement();
texp.setTextStyleNameAttribute("Contents_20_Heading");
texp.setTextContent("Table of Contents");
Iterator<Paragraph> paragraphIterator = getParagraphIterator();
while (paragraphIterator.hasNext()) {
Paragraph paragraph = paragraphIterator.next();
String text = paragraph.getTextContent();
String stylename = paragraph.getStyleName();
// Outline support
if (paragraph.isHeading()) {
int headingLevel = paragraph.getHeadingLevel();
if (stylename.length() <= 0) {
stylename = "Contents_20_" + headingLevel;
}
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
// end of Outline support
// Additional Styles support
if (tmptocstyleList.containsKey(stylename)) {
int headingLevel = tmptocstyleList.get(stylename);
stylename = "Contents_20_" + headingLevel;
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
// end of Additional Styles support
// Index Makes support
TextParagraphElementBase podf = paragraph.getOdfElement();
NodeList cns = podf.getChildNodes();
for (int i = 0; i < cns.getLength(); i++) {
Node node = cns.item(i);
if (node instanceof TextTocMarkElement) {
TextTocMarkElement textTocMarkElement = (TextTocMarkElement) node;
text = textTocMarkElement.getTextStringValueAttribute();
int headingLevel = textTocMarkElement
.getTextOutlineLevelAttribute();
stylename = "Contents_20_" + headingLevel;
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
if (node instanceof TextTocMarkStartElement) {
TextTocMarkStartElement textTocMarkStartElement = (TextTocMarkStartElement) node;
Node tmp = node.getNextSibling();
while (!(tmp instanceof Text)) {
tmp = node.getNextSibling();
}
text = tmp.getTextContent();
int headingLevel = textTocMarkStartElement
.getTextOutlineLevelAttribute();
stylename = "Contents_20_" + headingLevel;
ceateIndexBodyEntry(textIndexBody, stylename, text);
}
}
// end of Index Makes support
}
if (before) {
rootNode.insertBefore(textTableOfContent, refparagraphNode);
} else {
// Insert TOC after the refParagraph
Node refNextNode = refparagraphNode.getNextSibling();
if (refNextNode == null) {
rootNode.appendChild(textTableOfContent);
} else {
rootNode.insertBefore(textTableOfContent, refNextNode);
}
}
return textTableOfContent;
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
"Failed to create Default TOC", e);
throw new RuntimeException("Failed to create Default TOC", e);
}
}
/**
* Copy a Paragraph and insert it before or after the Reference Paragraph in the text document, whether the
* Paragraph is in this document or in a different document.
*
* @param referenceParagraph
* - where the Paragraph be inserted
* @param sourceParagraph
* - the Paragraph which will be copied
* @param before
* true:insert Paragraph before the reference paragraph.
* false:insert Paragraph after the reference paragraph.
*/
public Paragraph insertParagraph(Paragraph referenceParagraph, Paragraph sourceParagraph,boolean before) {
boolean isForeignNode = false;
try {
Node refparagraphNode = referenceParagraph.getOdfElement();
if (sourceParagraph.getOdfElement().getOwnerDocument() != getContentDom())
isForeignNode = true;
TextParagraphElementBase oldParagraphEle = sourceParagraph.getOdfElement();
TextParagraphElementBase newParagraphEle = (TextParagraphElementBase) oldParagraphEle.cloneNode(true);
if (isForeignNode)
copyForeignStyleRef(sourceParagraph.getOdfElement(), sourceParagraph.getOwnerDocument());
if (isForeignNode) // not in a same document
newParagraphEle = (TextParagraphElementBase) cloneForeignElement(newParagraphEle, getContentDom(), true);
if (before) {
refparagraphNode.getParentNode().insertBefore(newParagraphEle, refparagraphNode);
} else {
// Insert Paragraph after the refParagraph
Node refNextNode = refparagraphNode.getNextSibling();
if (refNextNode == null) {
refparagraphNode.getParentNode().appendChild(newParagraphEle);
} else {
refparagraphNode.getParentNode().insertBefore(newParagraphEle, refNextNode);
}
}
return Paragraph.getInstanceof(newParagraphEle);
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return null;
}
/**
* Copy a Table and insert it before or after the Reference Paragraph in the text document, whether the
* Table is in this TextDocument or in a different Document.
*
* @param referenceParagraph
* - where the Paragraph be inserted
* @param sourceParagraph
* - the Paragraph which will be copied
* @param before
* true:insert Paragraph before the reference paragraph.
* false:insert Paragraph after the reference paragraph.
*/
public Table insertTable(Paragraph referenceParagraph, Table sourceTable,boolean before) {
Document ownDocument = sourceTable.getOwnerDocument();
TableTableElement newTEle = (TableTableElement)insertOdfElement(referenceParagraph.getOdfElement(),ownDocument,sourceTable.getOdfElement(),before);
Table table = Table.getInstance(newTEle);
return table;
}
/**
* Copy a OdfElement and insert it before or after the Reference OdfElement in the TextDocument, whether the
* OdfElement is in this TextDocument or in a different Document.
*
* @param referenceOdfElement
* - where the OdfElement be inserted
* @param sourceDocument
* - the source Document which contain the sourceOdfElement
* @param sourceOdfElement
* - the OdfElement which will be copied
* @param before
* true:insert OdfElement before the reference OdfElement.
* false:insert OdfElement after the reference OdfElement.
*/
public OdfElement insertOdfElement(OdfElement referenceOdfElement,Document sourceDocument ,OdfElement sourceOdfElement,boolean before) {
boolean isForeignNode = false;
try {
if (sourceOdfElement.getOwnerDocument() != getContentDom())
isForeignNode = true;
OdfElement newOdfElement = (OdfElement) sourceOdfElement.cloneNode(true);
if (isForeignNode) {
copyForeignStyleRef(newOdfElement, sourceDocument);
copyLinkedRef(newOdfElement);
newOdfElement = (OdfElement) cloneForeignElement(newOdfElement,
getContentDom(), true);
}
if (before) {
referenceOdfElement.getParentNode().insertBefore(newOdfElement, referenceOdfElement);
} else {
// Insert newOdfElement after the referenceOdfElement
Node refNextNode = referenceOdfElement.getNextSibling();
if (refNextNode == null) {
referenceOdfElement.getParentNode().appendChild(newOdfElement);
} else {
referenceOdfElement.getParentNode().insertBefore(newOdfElement, refNextNode);
}
}
return newOdfElement;
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return null;
}
private OdfElement insertOdfElementwithoutstyle(OdfElement referenceOdfElement,Document sourceDocument ,OdfElement sourceOdfElement,boolean before) {
try {
OdfElement newOdfElement = (OdfElement) sourceOdfElement.cloneNode(true);
newOdfElement = (OdfElement) cloneForeignElement(newOdfElement, getContentDom(), true);
if (before) {
referenceOdfElement.getParentNode().insertBefore(newOdfElement, referenceOdfElement);
} else {
// Insert newOdfElement after the referenceOdfElement
Node refNextNode = referenceOdfElement.getNextSibling();
if (refNextNode == null) {
referenceOdfElement.getParentNode().appendChild(newOdfElement);
} else {
referenceOdfElement.getParentNode().insertBefore(newOdfElement, refNextNode);
}
}
return newOdfElement;
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
return null;
}
/**
* Copy text content of the source TextDocument and insert it to the current TextDocument
* after the reference Paragraph, with Styles or without Styles.
*
* @param sourceDocument
* the source TextDocument
* @param referenceParagraph
* where the text content of the source TextDocument be inserted
* @param isCopyStyle
* true:copy the styles in source document to current TextDocment.
* false:don't copy the styles in source document to current TextDocment.
*/
public void insertContentFromDocumentAfter(TextDocument sourceDocument, Paragraph referenceParagraph, boolean isCopyStyle){
try {
OfficeTextElement sroot = sourceDocument.getContentRoot();
NodeList clist = sroot.getChildNodes();
for (int i=(clist.getLength()-1); i>=0; i--) {
OdfElement node = (OdfElement) clist.item(i);
if(isCopyStyle){
insertOdfElement(referenceParagraph.getOdfElement(), sourceDocument, node, false);
}
else {
insertOdfElementwithoutstyle(referenceParagraph.getOdfElement(), sourceDocument, node, false);
}
}
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
}
/**
* Copy text content of the source TextDocument and insert it to the current TextDocument
* before the reference Paragraph, with Styles or without Styles.
*
* @param srcDoc
* the source TextDocument
* @param referenceParagraph
* where the text content of the source TextDocument be inserted
* @param isCopyStyle
* true:copy the styles in source document to current TextDocment.
* false:don't copy the styles in source document to current TextDocment.
*/
public void insertContentFromDocumentBefore(TextDocument sourceDocument, Paragraph referenceParagraph, boolean isCopyStyle){
try {
OfficeTextElement sroot = sourceDocument.getContentRoot();
NodeList clist = sroot.getChildNodes();
for (int i = 0; i < clist.getLength(); i++) {
OdfElement node = (OdfElement) clist.item(i);
if(isCopyStyle){
insertOdfElement(referenceParagraph.getOdfElement(), sourceDocument, node, true);
}
else {
insertOdfElementwithoutstyle(referenceParagraph.getOdfElement(), sourceDocument, node, true);
}
}
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE, null, e);
}
}
private FormContainerImpl getFormContainerImpl() {
if (formContainerImpl == null) {
formContainerImpl = new FormContainerImpl();
}
return formContainerImpl;
}
private class FormContainerImpl extends AbstractFormContainer {
public OfficeFormsElement getFormContainerElement() {
OfficeFormsElement forms = null;
try {
OfficeTextElement root = getContentRoot();
forms = OdfElement.findFirstChildNode(OfficeFormsElement.class,
root);
if (forms == null) {
Node firstChild = root.getFirstChild();
OfficeFormsElement officeForms = ((OdfFileDom) getContentDom())
.newOdfElement(OfficeFormsElement.class);
forms = (OfficeFormsElement) root.insertBefore(officeForms,
firstChild);
}
return forms;
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(
Level.SEVERE, null, e);
}
return forms;
}
}
/**
* Create a form with specified name in this text document.
*
* @see FormContainer#createForm(String)
*/
public Form createForm(String name) {
return getFormContainerImpl().createForm(name);
}
/**
* Get a form iterator to traverse all the forms in this document.
*
* @see FormContainer#getFormIterator()
*/
public Iterator<Form> getFormIterator() {
return getFormContainerImpl().getFormIterator();
}
/**
* Remove a form with the specified name in this document.
*
* @see FormContainer#removeForm(Form)
*/
public boolean removeForm(Form form) {
return getFormContainerImpl().removeForm(form);
}
// @Override
public Form getFormByName(String name) {
return getFormContainerImpl().getFormByName(name);
}
// @Override
public OfficeFormsElement getFormContainerElement() {
return getFormContainerImpl().getFormContainerElement();
}
// @Override
public boolean getApplyDesignMode() {
return getFormContainerImpl().getApplyDesignMode();
}
// @Override
public boolean getAutomaticFocus() {
return getFormContainerImpl().getAutomaticFocus();
}
// @Override
public void setApplyDesignMode(boolean isDesignMode) {
getFormContainerImpl().setApplyDesignMode(isDesignMode);
}
// @Override
public void setAutomaticFocus(boolean isAutoFocus) {
getFormContainerImpl().setAutomaticFocus(isAutoFocus);
}
// @Override
public Control createDrawControl() {
OdfElement parent = this.getDrawControlContainerElement();
OdfFileDom ownerDom = (OdfFileDom) parent.getOwnerDocument();
DrawControlElement element = ownerDom
.newOdfElement(DrawControlElement.class);
Node refChild = OdfElement.findFirstChildNode(
TextSequenceDeclsElement.class, parent);
parent.insertBefore(element, refChild.getNextSibling());
Control control = new Control(element);
Component.registerComponent(control, element);
return control;
}
// @Override
public OdfElement getDrawControlContainerElement() {
OdfElement element = null;
try {
element = this.getContentRoot();
} catch (Exception e) {
Logger.getLogger(TextDocument.class.getName()).log(Level.SEVERE,
null, e);
}
return element;
}
}